autodiscover 1.0.1 → 1.0.3
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.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE/Bug_report.md +35 -0
- data/.github/ISSUE_TEMPLATE/Feature_request.md +26 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +14 -0
- data/.github/dependabot.yml +8 -0
- data/.github/workflows/ci.yml +76 -0
- data/.github/workflows/gem_push.yml +22 -0
- data/.rubocop.yml +32 -0
- data/CHANGELOG.md +26 -0
- data/Gemfile +10 -0
- data/README.md +9 -6
- data/RELEASING.md +19 -0
- data/Rakefile +8 -6
- data/autodiscover.gemspec +29 -21
- data/lib/autodiscover/client.rb +8 -4
- data/lib/autodiscover/debug.rb +4 -2
- data/lib/autodiscover/errors.rb +8 -0
- data/lib/autodiscover/pox_request.rb +17 -17
- data/lib/autodiscover/pox_response.rb +12 -9
- data/lib/autodiscover/server_version_parser.rb +24 -17
- data/lib/autodiscover/version.rb +4 -1
- data/lib/autodiscover.rb +17 -13
- data/test/test_helper.rb +11 -6
- data/test/units/client_test.rb +25 -18
- data/test/units/pox_request_test.rb +23 -22
- data/test/units/pox_response_test.rb +26 -24
- data/test/units/server_version_parser_test.rb +9 -7
- metadata +35 -30
- data/.travis.yml +0 -6
- data/CHANGELOG +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 42bb937ea02607755471da089c5d0f0aad97bbbe0d80ade0b21dd9aa9b41be5b
|
|
4
|
+
data.tar.gz: f5e7de49bcd2ce30b5e389a5c27a436b1f8dfddd0e10985e67091f9ca554377f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ad318499b7648ecc494b580c30e8ded169e14d1a4b1b2c7736a4fade65e8a756cadc2a6a8371f275cac4bbb418c8a3825beb4ca9ee74e4d91c530a3356f5adad
|
|
7
|
+
data.tar.gz: 3e30491df11b63a6b6b58f324e2ff376cae9aa04160ff072bda876e5e9a1d2e66d3af0ffdbd4437e52435e30ca65df9c4ef0c8974a8e9f96aa7b0600cd944f51
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Bug report
|
|
3
|
+
about: Create a bug report
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Please don't delete this template or we'll close your issue -->
|
|
8
|
+
<!-- Before creating an issue, please ensure you are using the latest version of autodiscover. -->
|
|
9
|
+
|
|
10
|
+
# Bug report
|
|
11
|
+
|
|
12
|
+
<!-- Please ask questions on StackOverflow. Questions or support requests will be closed. -->
|
|
13
|
+
<!-- https://stackoverflow.com/questions/ask?tags=autodiscover -->
|
|
14
|
+
|
|
15
|
+
**Current behavior:**
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
**Expected behavior:**
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
**Steps to reproduce current behavior:**
|
|
22
|
+
|
|
23
|
+
<!-- The more of the following you can give us, the faster we can reproduce and fix it. -->
|
|
24
|
+
|
|
25
|
+
* Client setup and the code you ran:
|
|
26
|
+
|
|
27
|
+
* The request XML autodiscover built (or just the part that's wrong):
|
|
28
|
+
|
|
29
|
+
* The response you got back (body, and for a transport issue the status and headers):
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
**System information:**
|
|
33
|
+
|
|
34
|
+
* ruby version:
|
|
35
|
+
* autodiscover version:
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Feature request
|
|
3
|
+
about: Suggest a new feature for autodiscover
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Please don't delete this template or we'll close your issue -->
|
|
8
|
+
|
|
9
|
+
## Feature request
|
|
10
|
+
|
|
11
|
+
<!-- Issues which contain questions or support requests will be closed. -->
|
|
12
|
+
|
|
13
|
+
**Motivation for this feature:**
|
|
14
|
+
|
|
15
|
+
<!-- Please describe the use case or problem this would solve. -->
|
|
16
|
+
|
|
17
|
+
**Proposed implementation:**
|
|
18
|
+
|
|
19
|
+
<!-- Please describe at least one proposed implementation design. -->
|
|
20
|
+
|
|
21
|
+
**Would this introduce a breaking change?**
|
|
22
|
+
|
|
23
|
+
<!-- If yes, please describe the impact and a migration path for existing applications. -->
|
|
24
|
+
|
|
25
|
+
**Are you willing to work on this yourself?**
|
|
26
|
+
yes
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
**What kind of change is this?**
|
|
2
|
+
|
|
3
|
+
<!-- E.g. a bugfix, feature, refactoring, build change, etc… -->
|
|
4
|
+
|
|
5
|
+
**Did you add tests for your changes?**
|
|
6
|
+
|
|
7
|
+
<!-- Note that we won't merge your changes if you don't add tests -->
|
|
8
|
+
|
|
9
|
+
**Summary of changes**
|
|
10
|
+
|
|
11
|
+
<!-- Explain the **motivation** for making this change. What existing problem does the pull request solve? -->
|
|
12
|
+
<!-- Try to link to an open issue for more information. -->
|
|
13
|
+
|
|
14
|
+
**Other information**
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read # checkout only, nothing else
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
audit:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
16
|
+
with:
|
|
17
|
+
persist-credentials: false
|
|
18
|
+
- uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
19
|
+
with:
|
|
20
|
+
ruby-version: "3.4"
|
|
21
|
+
bundler-cache: true
|
|
22
|
+
- name: Audit dependencies
|
|
23
|
+
run: bundle exec bundle-audit check --update
|
|
24
|
+
- name: Audit Ruby runtime
|
|
25
|
+
# CVE-2026-41316 is an ERB flaw fixed in Ruby 4.0.3 and not yet backported.
|
|
26
|
+
# Ignored on affected rubies only. See:
|
|
27
|
+
# https://www.ruby-lang.org/en/news/2026/04/21/erb-cve-2026-41316/
|
|
28
|
+
# https://github.com/advisories/GHSA-q339-8rmv-2mhv
|
|
29
|
+
run: |
|
|
30
|
+
ignore=""
|
|
31
|
+
if ruby -e 'exit 1 unless Gem::Version.new(RUBY_VERSION) < Gem::Version.new("4.0.3")'; then
|
|
32
|
+
ignore="--ignore CVE-2026-41316"
|
|
33
|
+
fi
|
|
34
|
+
bundle exec ruby-audit check $ignore
|
|
35
|
+
|
|
36
|
+
zizmor:
|
|
37
|
+
runs-on: ubuntu-latest
|
|
38
|
+
steps:
|
|
39
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
40
|
+
with:
|
|
41
|
+
persist-credentials: false
|
|
42
|
+
- name: Audit workflows
|
|
43
|
+
uses: zizmorcore/zizmor-action@53290badfa369cb0bf7ad16342cb62c2fa47ac7b # v0.8.0
|
|
44
|
+
with:
|
|
45
|
+
advanced-security: false # fail the build on findings instead of uploading SARIF
|
|
46
|
+
|
|
47
|
+
lint:
|
|
48
|
+
runs-on: ubuntu-latest
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
51
|
+
with:
|
|
52
|
+
persist-credentials: false
|
|
53
|
+
- uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
54
|
+
with:
|
|
55
|
+
ruby-version: "3.4"
|
|
56
|
+
bundler-cache: true
|
|
57
|
+
- name: RuboCop
|
|
58
|
+
run: bundle exec rubocop --format github
|
|
59
|
+
|
|
60
|
+
test:
|
|
61
|
+
runs-on: ubuntu-latest
|
|
62
|
+
strategy:
|
|
63
|
+
fail-fast: false
|
|
64
|
+
matrix:
|
|
65
|
+
ruby: ['3.0', '3.1', '3.2', '3.3', '3.4', '4.0']
|
|
66
|
+
steps:
|
|
67
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
68
|
+
with:
|
|
69
|
+
persist-credentials: false
|
|
70
|
+
- name: Set up Ruby
|
|
71
|
+
uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
72
|
+
with:
|
|
73
|
+
ruby-version: ${{ matrix.ruby }}
|
|
74
|
+
bundler-cache: true # bundle installs and caches dependencies
|
|
75
|
+
- name: Run tests
|
|
76
|
+
run: bundle exec rake --trace
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
name: Push gem
|
|
2
|
+
on:
|
|
3
|
+
release:
|
|
4
|
+
types: [published]
|
|
5
|
+
jobs:
|
|
6
|
+
push:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write
|
|
10
|
+
contents: write
|
|
11
|
+
environment: release
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
|
14
|
+
with:
|
|
15
|
+
persist-credentials: false
|
|
16
|
+
- uses: ruby/setup-ruby@7f797815d8adceb1c412e7abefdd1ab4abc47a5f # v1.335.0
|
|
17
|
+
with:
|
|
18
|
+
ruby-version: "3"
|
|
19
|
+
bundler-cache: false
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: bundle install
|
|
22
|
+
- uses: rubygems/release-gem@7f9650160c1a4e7989fdc9855807bdbd421d8b6b # v1.4.1
|
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
plugins:
|
|
2
|
+
- rubocop-rake
|
|
3
|
+
|
|
4
|
+
AllCops:
|
|
5
|
+
TargetRubyVersion: 3.0
|
|
6
|
+
SuggestExtensions: true
|
|
7
|
+
NewCops: disable
|
|
8
|
+
|
|
9
|
+
Gemspec/RequireMFA:
|
|
10
|
+
Enabled: true
|
|
11
|
+
|
|
12
|
+
# required_ruby_version is intentionally left at >= 2.1.0 (library still
|
|
13
|
+
# supports older rubies); do not force it to match TargetRubyVersion.
|
|
14
|
+
Gemspec/RequiredRubyVersion:
|
|
15
|
+
Enabled: false
|
|
16
|
+
|
|
17
|
+
Metrics/BlockLength:
|
|
18
|
+
Exclude:
|
|
19
|
+
- 'test/**/*'
|
|
20
|
+
|
|
21
|
+
Layout/FirstHashElementIndentation:
|
|
22
|
+
EnforcedStyle: consistent
|
|
23
|
+
|
|
24
|
+
Layout/HashAlignment:
|
|
25
|
+
EnforcedHashRocketStyle: table
|
|
26
|
+
|
|
27
|
+
Style/BlockDelimiters:
|
|
28
|
+
EnforcedStyle: semantic
|
|
29
|
+
|
|
30
|
+
Style/HashSyntax:
|
|
31
|
+
EnforcedStyle: ruby19
|
|
32
|
+
EnforcedShorthandSyntax: never
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
*1.0.3* (2026-11-11)
|
|
2
|
+
|
|
3
|
+
* Detect Exchange 2013 SP1 by build number; add Exchange 2016/2019 version mappings
|
|
4
|
+
* Replace the `logging` gem with stdlib `logger`
|
|
5
|
+
* Add license to gemspec; CI modernization and README fixes
|
|
6
|
+
|
|
7
|
+
*1.0.2* (2016-10-11)
|
|
8
|
+
|
|
9
|
+
* Add configurable connection timeout, with a sensible default
|
|
10
|
+
* CI fixes (Travis/JRuby bundler issue; drop Rubinius from the matrix)
|
|
11
|
+
|
|
12
|
+
*1.0.1* (2016-09-13)
|
|
13
|
+
|
|
14
|
+
* Add basic logging for PoxRequest
|
|
15
|
+
* Keep going when the server refuses the connection (ECONNREFUSED)
|
|
16
|
+
|
|
17
|
+
*1.0.0* (2015-05-12)
|
|
18
|
+
|
|
19
|
+
* Major rewrite of the 1.x API (request/response classes restructured)
|
|
20
|
+
* Parse POX responses with Nori
|
|
21
|
+
* Add option to ignore SSL errors
|
|
22
|
+
* Rewritten README
|
|
23
|
+
|
|
24
|
+
*0.1.0*
|
|
25
|
+
|
|
26
|
+
* First public release
|
data/Gemfile
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
source 'https://rubygems.org'
|
|
2
4
|
|
|
3
5
|
# Specify your gem's dependencies in autodiscover.gemspec
|
|
4
6
|
gemspec
|
|
7
|
+
|
|
8
|
+
group :development do
|
|
9
|
+
gem 'bundler-audit', '~> 0.9.3', require: false
|
|
10
|
+
gem 'ostruct', require: false
|
|
11
|
+
gem 'rubocop', require: false
|
|
12
|
+
gem 'rubocop-rake', require: false
|
|
13
|
+
gem 'ruby_audit', '~> 3.1', require: false if RUBY_VERSION >= '3.1.0'
|
|
14
|
+
end
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://github.com/WinRb/autodiscover/actions/workflows/ci.yml)
|
|
2
2
|
|
|
3
3
|
Autodiscover
|
|
4
4
|
============
|
|
@@ -53,6 +53,9 @@ client = Autodiscover::Client.new(email: "blumbergh@initech.local", password: "t
|
|
|
53
53
|
# Override the domain
|
|
54
54
|
client = Autodiscover::Client.new(email: "blumbergh@initech.local", password: "tps_eq_awesome", domain: "tpsreports.local")
|
|
55
55
|
|
|
56
|
+
# Set a custom connection timeout
|
|
57
|
+
client = Autodiscover::Client.new(email: "blumbergh@initech.local", password: "tps_eq_awesome", connect_timeout: 5)
|
|
58
|
+
|
|
56
59
|
# Ignore SSL Errors
|
|
57
60
|
client.autodiscover(ignore_ssl_errors: true)
|
|
58
61
|
```
|
|
@@ -61,13 +64,13 @@ client.autodiscover(ignore_ssl_errors: true)
|
|
|
61
64
|
Installation
|
|
62
65
|
------------
|
|
63
66
|
|
|
64
|
-
### Configuring a Rails App to use the latest GitHub
|
|
67
|
+
### Configuring a Rails App to use the latest GitHub main version
|
|
65
68
|
|
|
66
|
-
gem 'autodiscover', :git => '
|
|
69
|
+
gem 'autodiscover', :git => 'https://github.com/WinRb/autodiscover.git'
|
|
67
70
|
|
|
68
|
-
### To install the latest development version from the GitHub
|
|
71
|
+
### To install the latest development version from the GitHub main
|
|
69
72
|
|
|
70
|
-
git clone
|
|
73
|
+
git clone https://github.com/WinRb/autodiscover.git
|
|
71
74
|
cd autodiscover
|
|
72
75
|
gem build autodiscover.gemspec
|
|
73
76
|
sudo gem install autodiscover-<version>.gem
|
|
@@ -79,4 +82,4 @@ Limitations:
|
|
|
79
82
|
|
|
80
83
|
* Doesn't support querying the DNS for SRV Records
|
|
81
84
|
|
|
82
|
-
Please submit additional bugs and issues here [
|
|
85
|
+
Please submit additional bugs and issues here [https://github.com/WinRb/autodiscover/issues](https://github.com/WinRb/autodiscover/issues)
|
data/RELEASING.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
_You'll need write access to the repository to create a release. Publishing is handled automatically via [trusted publishing](https://guides.rubygems.org/trusted-publishing/)._
|
|
2
|
+
|
|
3
|
+
## Cutting a release
|
|
4
|
+
|
|
5
|
+
1. On your release branch (e.g. `main`), edit [CHANGELOG](https://github.com/WinRb/autodiscover/blob/main/CHANGELOG.md) to finalize the new version number and list of all changes.
|
|
6
|
+
2. Bump [version.rb](https://github.com/WinRb/autodiscover/blob/main/lib/autodiscover/version.rb) to the version you picked in previous step.
|
|
7
|
+
3. **Final check**: make sure all tests are green, and that `rake build` succeeds. If not, merge any fixes back to the release branch and go to step 1.
|
|
8
|
+
4. [Draft a new release](https://github.com/WinRb/autodiscover/releases/new) on Github.
|
|
9
|
+
- In the "Choose a tag" field, type the version tag - e.g. `v0.2.0` - and select "Create new tag on publish".
|
|
10
|
+
- Use `v[version]` for the release title, and copy the changelog into the release notes.
|
|
11
|
+
- Click "Publish release". Github creates and pushes the tag, which triggers the release workflow.
|
|
12
|
+
5. Publishing to RubyGems.org is fully automated. The [Push gem workflow](https://github.com/WinRb/autodiscover/actions/workflows/gem_push.yml) triggers on the published release and requires approval from a release manager via the `release` environment before credentials are issued. **Before approving**: confirm that CI is green on the release commit. Approve the deployment in the Actions UI and the gem will be built and pushed automatically.
|
|
13
|
+
|
|
14
|
+
## Updating minimum ruby version
|
|
15
|
+
|
|
16
|
+
- Update `required_ruby_version` in [autodiscover.gemspec](https://github.com/WinRb/autodiscover/blob/main/autodiscover.gemspec)
|
|
17
|
+
- Update the test matrix in [ci.yml](https://github.com/WinRb/autodiscover/blob/main/.github/workflows/ci.yml)
|
|
18
|
+
- Update [README](https://github.com/WinRb/autodiscover/blob/main/README.md) with the correct support matrix
|
|
19
|
+
- Note the updated requirement in [CHANGELOG](https://github.com/WinRb/autodiscover/blob/main/CHANGELOG.md)
|
data/Rakefile
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
require "rake/testtask"
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
|
|
6
|
+
task default: :test
|
|
5
7
|
|
|
6
8
|
Rake::TestTask.new(:test) do |t|
|
|
7
9
|
t.libs << 'lib'
|
|
@@ -10,10 +12,10 @@ Rake::TestTask.new(:test) do |t|
|
|
|
10
12
|
t.verbose = false
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
desc
|
|
15
|
+
desc 'Open a Pry console for this library'
|
|
14
16
|
task :console do
|
|
15
|
-
require
|
|
16
|
-
require
|
|
17
|
+
require 'pry'
|
|
18
|
+
require 'autodiscover'
|
|
17
19
|
ARGV.clear
|
|
18
20
|
Pry.start
|
|
19
21
|
end
|
data/autodiscover.gemspec
CHANGED
|
@@ -1,31 +1,39 @@
|
|
|
1
|
-
#
|
|
2
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
5
|
require 'autodiscover/version'
|
|
5
6
|
|
|
6
7
|
Gem::Specification.new do |s|
|
|
7
|
-
s.name
|
|
8
|
-
s.version
|
|
9
|
-
s.
|
|
10
|
-
s.
|
|
8
|
+
s.name = 'autodiscover'
|
|
9
|
+
s.version = Autodiscover::VERSION
|
|
10
|
+
s.license = 'MIT'
|
|
11
|
+
s.metadata['rubygems_mfa_required'] = 'true'
|
|
12
|
+
s.summary = "Ruby client for Microsoft's Autodiscover Service"
|
|
13
|
+
s.description = 'The Autodiscover Service provides information about a ' \
|
|
14
|
+
'Microsoft Exchange environment such as service URLs, ' \
|
|
15
|
+
'versions and many other attributes.'
|
|
16
|
+
# NOTE: this floor is intentionally conservative for now. CI starts at Ruby 3.0 and older
|
|
17
|
+
# Rubies can't be validated, so it will likely move to 3.0 at the next release.
|
|
11
18
|
s.required_ruby_version = '>= 2.1.0'
|
|
12
19
|
|
|
13
|
-
s.authors
|
|
14
|
-
s.email
|
|
15
|
-
s.homepage
|
|
20
|
+
s.authors = ['David King', 'Dan Wanek']
|
|
21
|
+
s.email = ['dking@bestinclass.com', 'dan.wanek@gmail.com']
|
|
22
|
+
s.homepage = 'http://github.com/WinRb/autodiscover'
|
|
16
23
|
|
|
17
|
-
s.files
|
|
18
|
-
s.test_files
|
|
19
|
-
s.require_paths = [
|
|
24
|
+
s.files = `git ls-files -z`.split("\x0")
|
|
25
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
|
26
|
+
s.require_paths = ['lib']
|
|
20
27
|
|
|
21
|
-
s.add_runtime_dependency
|
|
22
|
-
|
|
23
|
-
s.add_runtime_dependency
|
|
24
|
-
s.add_runtime_dependency
|
|
28
|
+
s.add_runtime_dependency 'httpclient'
|
|
29
|
+
# logger is no longer a bundled gem on Ruby 4.0
|
|
30
|
+
s.add_runtime_dependency 'logger'
|
|
31
|
+
s.add_runtime_dependency 'nokogiri'
|
|
32
|
+
s.add_runtime_dependency 'nori'
|
|
25
33
|
|
|
26
|
-
s.add_development_dependency
|
|
27
|
-
s.add_development_dependency
|
|
28
|
-
s.add_development_dependency
|
|
29
|
-
s.add_development_dependency
|
|
30
|
-
s.add_development_dependency
|
|
34
|
+
s.add_development_dependency 'bundler'
|
|
35
|
+
s.add_development_dependency 'minitest', '~> 5.6.0'
|
|
36
|
+
s.add_development_dependency 'mocha', '~> 1.1.0'
|
|
37
|
+
s.add_development_dependency 'pry'
|
|
38
|
+
s.add_development_dependency 'rake'
|
|
31
39
|
end
|
data/lib/autodiscover/client.rb
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Ruby client for Microsoft's Autodiscover Service.
|
|
1
4
|
module Autodiscover
|
|
5
|
+
# Performs Autodiscover lookups against a Microsoft Exchange environment.
|
|
2
6
|
class Client
|
|
3
|
-
|
|
7
|
+
DEFAULT_HTTP_TIMEOUT = 10
|
|
4
8
|
attr_reader :domain, :email, :http
|
|
5
9
|
|
|
6
10
|
# @param email [String] An e-mail to use for autodiscovery. It will be
|
|
@@ -10,10 +14,11 @@ module Autodiscover
|
|
|
10
14
|
# with something other than the e-mail. For instance DOMAIN\user
|
|
11
15
|
# @param domain [String] An optional domain to provide as an override for
|
|
12
16
|
# the one parsed from the e-mail.
|
|
13
|
-
def initialize(email:, password:, username: nil, domain: nil)
|
|
17
|
+
def initialize(email:, password:, username: nil, domain: nil, connect_timeout: DEFAULT_HTTP_TIMEOUT)
|
|
14
18
|
@email = email
|
|
15
|
-
@domain = domain || @email.split(
|
|
19
|
+
@domain = domain || @email.split('@').last
|
|
16
20
|
@http = HTTPClient.new
|
|
21
|
+
@http.connect_timeout = connect_timeout if connect_timeout
|
|
17
22
|
@username = username || email
|
|
18
23
|
@http.set_auth(nil, @username, password)
|
|
19
24
|
end
|
|
@@ -28,6 +33,5 @@ module Autodiscover
|
|
|
28
33
|
raise Autodiscover::ArgumentError, "Not a valid autodiscover type (#{type})."
|
|
29
34
|
end
|
|
30
35
|
end
|
|
31
|
-
|
|
32
36
|
end
|
|
33
37
|
end
|
data/lib/autodiscover/debug.rb
CHANGED
data/lib/autodiscover/errors.rb
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Errors raised by the Autodiscover client.
|
|
1
4
|
module Autodiscover
|
|
5
|
+
# Base error for Autodiscover failures.
|
|
2
6
|
class Error < ::StandardError; end
|
|
3
7
|
|
|
8
|
+
# Raised when invalid arguments are given.
|
|
4
9
|
class ArgumentError < Error; end
|
|
10
|
+
|
|
11
|
+
# Raised when the server version cannot be determined.
|
|
12
|
+
class VersionError < Error; end
|
|
5
13
|
end
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# POX Autodiscover request handling.
|
|
1
4
|
module Autodiscover
|
|
5
|
+
# Performs the POX Autodiscover request against Exchange endpoints.
|
|
2
6
|
class PoxRequest
|
|
3
7
|
include Autodiscover
|
|
4
8
|
|
|
@@ -16,52 +20,49 @@ module Autodiscover
|
|
|
16
20
|
# @return [Autodiscover::PoxResponse, nil]
|
|
17
21
|
def autodiscover
|
|
18
22
|
available_urls.each do |url|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
options[:ignore_ssl_errors] ? next : raise
|
|
26
|
-
end
|
|
23
|
+
response = client.http.post(url, request_body, 'Content-Type' => 'text/xml; charset=utf-8')
|
|
24
|
+
return PoxResponse.new(response.body) if good_response?(response)
|
|
25
|
+
rescue Errno::ENETUNREACH, Errno::ECONNREFUSED, HTTPClient::ConnectTimeoutError
|
|
26
|
+
next
|
|
27
|
+
rescue OpenSSL::SSL::SSLError
|
|
28
|
+
options[:ignore_ssl_errors] ? next : raise
|
|
27
29
|
end
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
|
|
31
32
|
private
|
|
32
33
|
|
|
33
|
-
|
|
34
34
|
def good_response?(response)
|
|
35
35
|
response.status == 200
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def available_urls(&block)
|
|
39
39
|
return to_enum(__method__) unless block_given?
|
|
40
|
-
|
|
40
|
+
|
|
41
|
+
formatted_https_urls.each do |url|
|
|
41
42
|
logger.debug "Yielding HTTPS Url #{url}"
|
|
42
43
|
yield url
|
|
43
|
-
|
|
44
|
+
end
|
|
44
45
|
logger.debug "Yielding HTTP Redirected Url #{redirected_http_url}"
|
|
45
46
|
yield redirected_http_url
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def formatted_https_urls
|
|
49
|
-
@
|
|
50
|
+
@formatted_https_urls ||= %W[
|
|
50
51
|
https://#{client.domain}/autodiscover/autodiscover.xml
|
|
51
52
|
https://autodiscover.#{client.domain}/autodiscover/autodiscover.xml
|
|
52
|
-
|
|
53
|
+
]
|
|
53
54
|
end
|
|
54
55
|
|
|
55
56
|
def redirected_http_url
|
|
56
57
|
@redirected_http_url ||=
|
|
57
58
|
begin
|
|
58
59
|
response = client.http.get("http://autodiscover.#{client.domain}/autodiscover/autodiscover.xml")
|
|
59
|
-
|
|
60
|
+
response.status == 302 ? response.headers['Location'] : nil
|
|
60
61
|
end
|
|
61
62
|
end
|
|
62
63
|
|
|
63
64
|
def request_body
|
|
64
|
-
Nokogiri::XML::Builder.new do |xml|
|
|
65
|
+
Nokogiri::XML::Builder.new do |xml|
|
|
65
66
|
xml.Autodiscover('xmlns' => 'http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006') {
|
|
66
67
|
xml.Request {
|
|
67
68
|
xml.EMailAddress client.email
|
|
@@ -70,6 +71,5 @@ module Autodiscover
|
|
|
70
71
|
}
|
|
71
72
|
end.to_xml
|
|
72
73
|
end
|
|
73
|
-
|
|
74
74
|
end
|
|
75
75
|
end
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# POX Autodiscover response handling.
|
|
1
4
|
module Autodiscover
|
|
5
|
+
# Parses a POX Autodiscover XML response.
|
|
2
6
|
class PoxResponse
|
|
3
|
-
|
|
4
7
|
attr_reader :response
|
|
5
8
|
|
|
6
9
|
def initialize(response)
|
|
7
|
-
raise ArgumentError,
|
|
8
|
-
|
|
10
|
+
raise ArgumentError, 'Response must be an XML string' if response.nil? || response.empty?
|
|
11
|
+
|
|
12
|
+
@response = Nori.new(parser: :nokogiri).parse(response)['Autodiscover']['Response']
|
|
9
13
|
end
|
|
10
14
|
|
|
11
15
|
def exchange_version
|
|
12
|
-
ServerVersionParser.new(exch_proto[
|
|
16
|
+
ServerVersionParser.new(exch_proto['ServerVersion']).exchange_version
|
|
13
17
|
end
|
|
14
18
|
|
|
15
19
|
def ews_url
|
|
16
|
-
expr_proto[
|
|
20
|
+
expr_proto['EwsUrl']
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def exch_proto
|
|
20
|
-
@exch_proto ||=
|
|
24
|
+
@exch_proto ||= response['Account']['Protocol'].select { |p| p['Type'] == 'EXCH' }.first || {}
|
|
21
25
|
end
|
|
22
26
|
|
|
23
27
|
def expr_proto
|
|
24
|
-
@expr_proto ||=
|
|
28
|
+
@expr_proto ||= response['Account']['Protocol'].select { |p| p['Type'] == 'EXPR' }.first || {}
|
|
25
29
|
end
|
|
26
30
|
|
|
27
31
|
def web_proto
|
|
28
|
-
@web_proto ||=
|
|
32
|
+
@web_proto ||= response['Account']['Protocol'].select { |p| p['Type'] == 'WEB' }.first || {}
|
|
29
33
|
end
|
|
30
|
-
|
|
31
34
|
end
|
|
32
35
|
end
|
|
@@ -1,27 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Server version parsing for Autodiscover responses.
|
|
1
4
|
module Autodiscover
|
|
5
|
+
# Parses the hex ServerVersion from a POX response into an Exchange version.
|
|
2
6
|
class ServerVersionParser
|
|
3
|
-
|
|
4
7
|
VERSIONS = {
|
|
5
|
-
8
|
|
6
|
-
0 =>
|
|
7
|
-
1 =>
|
|
8
|
-
2 =>
|
|
9
|
-
3 =>
|
|
8
|
+
8 => {
|
|
9
|
+
0 => 'Exchange2007',
|
|
10
|
+
1 => 'Exchange2007_SP1',
|
|
11
|
+
2 => 'Exchange2007_SP1',
|
|
12
|
+
3 => 'Exchange2007_SP1'
|
|
10
13
|
},
|
|
11
14
|
14 => {
|
|
12
|
-
0 =>
|
|
13
|
-
1 =>
|
|
14
|
-
2 =>
|
|
15
|
-
3 =>
|
|
15
|
+
0 => 'Exchange2010',
|
|
16
|
+
1 => 'Exchange2010_SP1',
|
|
17
|
+
2 => 'Exchange2010_SP2',
|
|
18
|
+
3 => 'Exchange2010_SP2'
|
|
16
19
|
},
|
|
17
20
|
15 => {
|
|
18
|
-
0
|
|
19
|
-
1
|
|
21
|
+
0 => 'Exchange2013', # Minor builds starting from 847 are Exchange2013_SP1
|
|
22
|
+
1 => 'Exchange2016',
|
|
23
|
+
2 => 'Exchange2019',
|
|
24
|
+
20 => 'Exchange2016' # This is Office365
|
|
20
25
|
}
|
|
21
|
-
}
|
|
26
|
+
}.freeze
|
|
22
27
|
|
|
23
28
|
def initialize(hexversion)
|
|
24
|
-
@version = hexversion.hex.to_s(2).rjust(hexversion.size*4, '0')
|
|
29
|
+
@version = hexversion.hex.to_s(2).rjust(hexversion.size * 4, '0')
|
|
25
30
|
end
|
|
26
31
|
|
|
27
32
|
def major
|
|
@@ -37,9 +42,11 @@ module Autodiscover
|
|
|
37
42
|
end
|
|
38
43
|
|
|
39
44
|
def exchange_version
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
end
|
|
45
|
+
version = VERSIONS[major][minor]
|
|
46
|
+
raise VersionError, "Unknown version string: #{@version}" unless version
|
|
43
47
|
|
|
48
|
+
version = 'Exchange2013_SP1' if version == 'Exchange2013' && build >= 847
|
|
49
|
+
version
|
|
50
|
+
end
|
|
44
51
|
end
|
|
45
52
|
end
|
data/lib/autodiscover/version.rb
CHANGED
data/lib/autodiscover.rb
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
require "nokogiri"
|
|
3
|
-
require "nori"
|
|
4
|
-
require "httpclient"
|
|
5
|
-
require "logging"
|
|
1
|
+
# frozen_string_literal: true
|
|
6
2
|
|
|
3
|
+
require 'autodiscover/version'
|
|
4
|
+
require 'nokogiri'
|
|
5
|
+
require 'nori'
|
|
6
|
+
require 'httpclient'
|
|
7
|
+
require 'logger' unless defined?(Logger)
|
|
8
|
+
|
|
9
|
+
# Ruby client for Microsoft's Autodiscover Service.
|
|
7
10
|
module Autodiscover
|
|
8
|
-
|
|
11
|
+
@logger = Logger.new($stdout)
|
|
12
|
+
@logger.level = Logger::INFO
|
|
9
13
|
|
|
10
14
|
def self.logger
|
|
11
|
-
|
|
15
|
+
@logger
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
def logger
|
|
15
|
-
@logger ||=
|
|
19
|
+
@logger ||= Autodiscover.logger
|
|
16
20
|
end
|
|
17
21
|
end
|
|
18
22
|
|
|
19
|
-
require
|
|
20
|
-
require
|
|
21
|
-
require
|
|
22
|
-
require
|
|
23
|
-
require
|
|
23
|
+
require 'autodiscover/errors'
|
|
24
|
+
require 'autodiscover/client'
|
|
25
|
+
require 'autodiscover/pox_request'
|
|
26
|
+
require 'autodiscover/pox_response'
|
|
27
|
+
require 'autodiscover/server_version_parser'
|
data/test/test_helper.rb
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require File.expand_path('../lib/autodiscover.rb', __dir__)
|
|
2
4
|
require 'minitest/autorun'
|
|
3
|
-
require
|
|
4
|
-
require "mocha/mini_test"
|
|
5
|
+
require 'mocha/mini_test'
|
|
5
6
|
|
|
6
7
|
TEST_DIR = File.dirname(__FILE__)
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
# Helpers for the minitest specs.
|
|
10
|
+
module MiniTest
|
|
11
|
+
# Spec helpers.
|
|
12
|
+
class Spec
|
|
13
|
+
def load_sample(name)
|
|
14
|
+
File.read("#{TEST_DIR}/fixtures/#{name}")
|
|
15
|
+
end
|
|
11
16
|
end
|
|
12
17
|
end
|
data/test/units/client_test.rb
CHANGED
|
@@ -1,35 +1,42 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
# Tests for Autodiscover::Client.
|
|
3
6
|
describe Autodiscover::Client do
|
|
4
7
|
let(:_class) { Autodiscover::Client }
|
|
5
8
|
|
|
6
|
-
describe
|
|
7
|
-
|
|
8
|
-
inst = _class.new(email:
|
|
9
|
-
_(inst.domain).must_equal
|
|
10
|
-
_(inst.instance_variable_get(:@username)).must_equal
|
|
9
|
+
describe '#initialize' do
|
|
10
|
+
it 'sets a username and domain from the email' do
|
|
11
|
+
inst = _class.new(email: 'test@example.local', password: 'test')
|
|
12
|
+
_(inst.domain).must_equal 'example.local'
|
|
13
|
+
_(inst.instance_variable_get(:@username)).must_equal 'test@example.local'
|
|
11
14
|
end
|
|
12
15
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
it 'allows you to override the username and domain' do
|
|
17
|
+
inst = _class.new(
|
|
18
|
+
email: 'test@example.local',
|
|
19
|
+
password: 'test',
|
|
20
|
+
username: 'DOMAIN\test',
|
|
21
|
+
domain: 'otherexample.local'
|
|
22
|
+
)
|
|
23
|
+
_(inst.domain).must_equal 'otherexample.local'
|
|
16
24
|
_(inst.instance_variable_get(:@username)).must_equal 'DOMAIN\test'
|
|
17
25
|
end
|
|
18
26
|
end
|
|
19
27
|
|
|
20
|
-
describe
|
|
21
|
-
it
|
|
22
|
-
inst = _class.new(email:
|
|
23
|
-
pox_request = mock(
|
|
28
|
+
describe '#autodiscover' do
|
|
29
|
+
it 'dispatches autodiscover to a PoxRequest instance' do
|
|
30
|
+
inst = _class.new(email: 'test@example.local', password: 'test')
|
|
31
|
+
pox_request = mock('pox')
|
|
24
32
|
pox_request.expects(:autodiscover)
|
|
25
|
-
Autodiscover::PoxRequest.expects(:new).with(inst
|
|
33
|
+
Autodiscover::PoxRequest.expects(:new).with(inst).returns(pox_request)
|
|
26
34
|
inst.autodiscover
|
|
27
35
|
end
|
|
28
36
|
|
|
29
|
-
it
|
|
30
|
-
inst = _class.new(email:
|
|
31
|
-
->{ inst.autodiscover(type: :invalid) }.must_raise(Autodiscover::ArgumentError)
|
|
37
|
+
it 'raises an exception if an invalid autodiscover type is passed' do
|
|
38
|
+
inst = _class.new(email: 'test@example.local', password: 'test')
|
|
39
|
+
-> { inst.autodiscover(type: :invalid) }.must_raise(Autodiscover::ArgumentError)
|
|
32
40
|
end
|
|
33
41
|
end
|
|
34
|
-
|
|
35
42
|
end
|
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
|
|
2
|
-
require "ostruct"
|
|
1
|
+
# frozen_string_literal: true
|
|
3
2
|
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
require 'ostruct'
|
|
5
|
+
|
|
6
|
+
# Tests for Autodiscover::PoxRequest.
|
|
4
7
|
describe Autodiscover::PoxRequest do
|
|
5
|
-
let(:_class) {Autodiscover::PoxRequest }
|
|
6
|
-
let(:http) { mock(
|
|
7
|
-
let(:client) { OpenStruct.new(
|
|
8
|
+
let(:_class) { Autodiscover::PoxRequest }
|
|
9
|
+
let(:http) { mock('http') }
|
|
10
|
+
let(:client) { OpenStruct.new(http: http, domain: 'example.local', email: 'test@example.local') }
|
|
8
11
|
|
|
9
|
-
describe
|
|
10
|
-
it
|
|
11
|
-
request_body =
|
|
12
|
+
describe '#autodiscover' do
|
|
13
|
+
it 'returns a PoxResponse if the autodiscover is successful' do
|
|
14
|
+
request_body = <<~REQUEST_XML
|
|
12
15
|
<?xml version="1.0"?>
|
|
13
16
|
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/requestschema/2006">
|
|
14
17
|
<Request>
|
|
@@ -16,31 +19,29 @@ describe Autodiscover::PoxRequest do
|
|
|
16
19
|
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
|
|
17
20
|
</Request>
|
|
18
21
|
</Autodiscover>
|
|
19
|
-
|
|
22
|
+
REQUEST_XML
|
|
20
23
|
http.expects(:post).with(
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
).returns(OpenStruct.new(
|
|
24
|
+
'https://example.local/autodiscover/autodiscover.xml', request_body,
|
|
25
|
+
'Content-Type' => 'text/xml; charset=utf-8'
|
|
26
|
+
).returns(OpenStruct.new(status: 200, body: '<Autodiscover><Response><test></test></Response></Autodiscover>'))
|
|
24
27
|
|
|
25
28
|
inst = _class.new(client)
|
|
26
29
|
_(inst.autodiscover).must_be_instance_of(Autodiscover::PoxResponse)
|
|
27
30
|
end
|
|
28
31
|
|
|
29
|
-
it
|
|
30
|
-
http.expects(:post).raises(OpenSSL::SSL::SSLError,
|
|
32
|
+
it 'will fail if :ignore_ssl_errors is not true' do
|
|
33
|
+
http.expects(:post).raises(OpenSSL::SSL::SSLError, 'Test Error')
|
|
31
34
|
inst = _class.new(client)
|
|
32
|
-
-> {inst.autodiscover}.must_raise(OpenSSL::SSL::SSLError)
|
|
35
|
+
-> { inst.autodiscover }.must_raise(OpenSSL::SSL::SSLError)
|
|
33
36
|
end
|
|
34
37
|
|
|
35
|
-
it
|
|
36
|
-
http.expects(:get).once.returns(OpenStruct.new(
|
|
37
|
-
http.expects(:post).times(3).
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
raises(Errno::ENETUNREACH, "Test Error")
|
|
38
|
+
it 'keeps trying if :ignore_ssl_errors is set' do
|
|
39
|
+
http.expects(:get).once.returns(OpenStruct.new(headers: { 'Location' => 'http://example.local' }, status: 302))
|
|
40
|
+
http.expects(:post).times(3).raises(OpenSSL::SSL::SSLError, 'Test Error')
|
|
41
|
+
.then.raises(OpenSSL::SSL::SSLError, 'Test Error')
|
|
42
|
+
.then.raises(Errno::ENETUNREACH, 'Test Error')
|
|
41
43
|
inst = _class.new(client, ignore_ssl_errors: true)
|
|
42
44
|
_(inst.autodiscover).must_be_nil
|
|
43
45
|
end
|
|
44
|
-
|
|
45
46
|
end
|
|
46
47
|
end
|
|
@@ -1,54 +1,56 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
# Tests for Autodiscover::PoxResponse.
|
|
3
6
|
describe Autodiscover::PoxResponse do
|
|
4
|
-
let(:_class) {Autodiscover::PoxResponse }
|
|
5
|
-
let(:response) { load_sample(
|
|
7
|
+
let(:_class) { Autodiscover::PoxResponse }
|
|
8
|
+
let(:response) { load_sample('pox_response.xml') }
|
|
6
9
|
|
|
7
|
-
describe
|
|
8
|
-
it
|
|
10
|
+
describe '#initialize' do
|
|
11
|
+
it 'parses an XML string into a Hash when initialized' do
|
|
9
12
|
inst = _class.new response
|
|
10
13
|
_(inst.response).must_be_instance_of Hash
|
|
11
14
|
end
|
|
12
15
|
|
|
13
|
-
it
|
|
14
|
-
->{_class.new
|
|
15
|
-
->{_class.new nil}.must_raise(Autodiscover::ArgumentError)
|
|
16
|
+
it 'it raises an exception if the response is empty or nil' do
|
|
17
|
+
-> { _class.new '' }.must_raise(Autodiscover::ArgumentError)
|
|
18
|
+
-> { _class.new nil }.must_raise(Autodiscover::ArgumentError)
|
|
16
19
|
end
|
|
17
20
|
end
|
|
18
21
|
|
|
19
|
-
describe
|
|
20
|
-
it
|
|
21
|
-
_(_class.new(response).exchange_version).must_equal
|
|
22
|
+
describe '#exchange_version' do
|
|
23
|
+
it 'returns an Exchange version usable for EWS' do
|
|
24
|
+
_(_class.new(response).exchange_version).must_equal 'Exchange2016'
|
|
22
25
|
end
|
|
23
26
|
end
|
|
24
27
|
|
|
25
|
-
describe
|
|
26
|
-
it
|
|
27
|
-
_(_class.new(response).ews_url).must_equal
|
|
28
|
+
describe '#ews_url' do
|
|
29
|
+
it 'returns the EWS url' do
|
|
30
|
+
_(_class.new(response).ews_url).must_equal 'https://outlook.office365.com/EWS/Exchange.asmx'
|
|
28
31
|
end
|
|
29
32
|
end
|
|
30
33
|
|
|
31
|
-
describe
|
|
34
|
+
describe 'Protocol Hashes' do
|
|
32
35
|
let(:_inst) { _class.new(response) }
|
|
33
36
|
|
|
34
|
-
it
|
|
35
|
-
_(_inst.exch_proto[
|
|
37
|
+
it 'returns the EXCH protocol Hash' do
|
|
38
|
+
_(_inst.exch_proto['Type']).must_equal 'EXCH'
|
|
36
39
|
end
|
|
37
40
|
|
|
38
|
-
it
|
|
39
|
-
_(_inst.expr_proto[
|
|
41
|
+
it 'returns the EXPR protocol Hash' do
|
|
42
|
+
_(_inst.expr_proto['Type']).must_equal 'EXPR'
|
|
40
43
|
end
|
|
41
44
|
|
|
42
|
-
it
|
|
43
|
-
_(_inst.web_proto[
|
|
45
|
+
it 'returns the WEB protocol Hash' do
|
|
46
|
+
_(_inst.web_proto['Type']).must_equal 'WEB'
|
|
44
47
|
end
|
|
45
48
|
|
|
46
|
-
it
|
|
47
|
-
_inst.response[
|
|
49
|
+
it 'returns empty Hashes when the protocols are missing' do
|
|
50
|
+
_inst.response['Account']['Protocol'] = []
|
|
48
51
|
_(_inst.exch_proto).must_equal({})
|
|
49
52
|
_(_inst.expr_proto).must_equal({})
|
|
50
53
|
_(_inst.web_proto).must_equal({})
|
|
51
54
|
end
|
|
52
55
|
end
|
|
53
|
-
|
|
54
56
|
end
|
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
# Tests for Autodiscover::ServerVersionParser.
|
|
3
6
|
describe Autodiscover::ServerVersionParser do
|
|
4
7
|
let(:_class) { Autodiscover::ServerVersionParser }
|
|
5
8
|
|
|
6
|
-
it
|
|
7
|
-
inst = _class.new(
|
|
9
|
+
it 'parses a hex ServerVersion response' do
|
|
10
|
+
inst = _class.new('738180DA')
|
|
8
11
|
_(inst.major).must_equal 14
|
|
9
12
|
_(inst.minor).must_equal 1
|
|
10
13
|
_(inst.build).must_equal 218
|
|
11
14
|
end
|
|
12
15
|
|
|
13
|
-
it
|
|
14
|
-
inst = _class.new(
|
|
15
|
-
inst.exchange_version.must_equal
|
|
16
|
+
it 'returns an Exchange Server Version' do
|
|
17
|
+
inst = _class.new('738180DA')
|
|
18
|
+
inst.exchange_version.must_equal 'Exchange2010_SP1'
|
|
16
19
|
end
|
|
17
|
-
|
|
18
20
|
end
|
metadata
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: autodiscover
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David King
|
|
8
8
|
- Dan Wanek
|
|
9
|
-
autorequire:
|
|
10
9
|
bindir: bin
|
|
11
10
|
cert_chain: []
|
|
12
|
-
date:
|
|
11
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
13
12
|
dependencies:
|
|
14
13
|
- !ruby/object:Gem::Dependency
|
|
15
|
-
name:
|
|
14
|
+
name: httpclient
|
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
|
17
16
|
requirements:
|
|
18
17
|
- - ">="
|
|
@@ -26,7 +25,7 @@ dependencies:
|
|
|
26
25
|
- !ruby/object:Gem::Version
|
|
27
26
|
version: '0'
|
|
28
27
|
- !ruby/object:Gem::Dependency
|
|
29
|
-
name:
|
|
28
|
+
name: logger
|
|
30
29
|
requirement: !ruby/object:Gem::Requirement
|
|
31
30
|
requirements:
|
|
32
31
|
- - ">="
|
|
@@ -40,7 +39,7 @@ dependencies:
|
|
|
40
39
|
- !ruby/object:Gem::Version
|
|
41
40
|
version: '0'
|
|
42
41
|
- !ruby/object:Gem::Dependency
|
|
43
|
-
name:
|
|
42
|
+
name: nokogiri
|
|
44
43
|
requirement: !ruby/object:Gem::Requirement
|
|
45
44
|
requirements:
|
|
46
45
|
- - ">="
|
|
@@ -54,7 +53,7 @@ dependencies:
|
|
|
54
53
|
- !ruby/object:Gem::Version
|
|
55
54
|
version: '0'
|
|
56
55
|
- !ruby/object:Gem::Dependency
|
|
57
|
-
name:
|
|
56
|
+
name: nori
|
|
58
57
|
requirement: !ruby/object:Gem::Requirement
|
|
59
58
|
requirements:
|
|
60
59
|
- - ">="
|
|
@@ -68,49 +67,49 @@ dependencies:
|
|
|
68
67
|
- !ruby/object:Gem::Version
|
|
69
68
|
version: '0'
|
|
70
69
|
- !ruby/object:Gem::Dependency
|
|
71
|
-
name:
|
|
70
|
+
name: bundler
|
|
72
71
|
requirement: !ruby/object:Gem::Requirement
|
|
73
72
|
requirements:
|
|
74
|
-
- - "
|
|
73
|
+
- - ">="
|
|
75
74
|
- !ruby/object:Gem::Version
|
|
76
|
-
version:
|
|
75
|
+
version: '0'
|
|
77
76
|
type: :development
|
|
78
77
|
prerelease: false
|
|
79
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
80
79
|
requirements:
|
|
81
|
-
- - "
|
|
80
|
+
- - ">="
|
|
82
81
|
- !ruby/object:Gem::Version
|
|
83
|
-
version:
|
|
82
|
+
version: '0'
|
|
84
83
|
- !ruby/object:Gem::Dependency
|
|
85
|
-
name:
|
|
84
|
+
name: minitest
|
|
86
85
|
requirement: !ruby/object:Gem::Requirement
|
|
87
86
|
requirements:
|
|
88
87
|
- - "~>"
|
|
89
88
|
- !ruby/object:Gem::Version
|
|
90
|
-
version:
|
|
89
|
+
version: 5.6.0
|
|
91
90
|
type: :development
|
|
92
91
|
prerelease: false
|
|
93
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
94
93
|
requirements:
|
|
95
94
|
- - "~>"
|
|
96
95
|
- !ruby/object:Gem::Version
|
|
97
|
-
version:
|
|
96
|
+
version: 5.6.0
|
|
98
97
|
- !ruby/object:Gem::Dependency
|
|
99
|
-
name:
|
|
98
|
+
name: mocha
|
|
100
99
|
requirement: !ruby/object:Gem::Requirement
|
|
101
100
|
requirements:
|
|
102
|
-
- - "
|
|
101
|
+
- - "~>"
|
|
103
102
|
- !ruby/object:Gem::Version
|
|
104
|
-
version:
|
|
103
|
+
version: 1.1.0
|
|
105
104
|
type: :development
|
|
106
105
|
prerelease: false
|
|
107
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
108
107
|
requirements:
|
|
109
|
-
- - "
|
|
108
|
+
- - "~>"
|
|
110
109
|
- !ruby/object:Gem::Version
|
|
111
|
-
version:
|
|
110
|
+
version: 1.1.0
|
|
112
111
|
- !ruby/object:Gem::Dependency
|
|
113
|
-
name:
|
|
112
|
+
name: pry
|
|
114
113
|
requirement: !ruby/object:Gem::Requirement
|
|
115
114
|
requirements:
|
|
116
115
|
- - ">="
|
|
@@ -124,7 +123,7 @@ dependencies:
|
|
|
124
123
|
- !ruby/object:Gem::Version
|
|
125
124
|
version: '0'
|
|
126
125
|
- !ruby/object:Gem::Dependency
|
|
127
|
-
name:
|
|
126
|
+
name: rake
|
|
128
127
|
requirement: !ruby/object:Gem::Requirement
|
|
129
128
|
requirements:
|
|
130
129
|
- - ">="
|
|
@@ -146,12 +145,19 @@ executables: []
|
|
|
146
145
|
extensions: []
|
|
147
146
|
extra_rdoc_files: []
|
|
148
147
|
files:
|
|
148
|
+
- ".github/ISSUE_TEMPLATE/Bug_report.md"
|
|
149
|
+
- ".github/ISSUE_TEMPLATE/Feature_request.md"
|
|
150
|
+
- ".github/PULL_REQUEST_TEMPLATE.md"
|
|
151
|
+
- ".github/dependabot.yml"
|
|
152
|
+
- ".github/workflows/ci.yml"
|
|
153
|
+
- ".github/workflows/gem_push.yml"
|
|
149
154
|
- ".gitignore"
|
|
150
|
-
- ".
|
|
151
|
-
- CHANGELOG
|
|
155
|
+
- ".rubocop.yml"
|
|
156
|
+
- CHANGELOG.md
|
|
152
157
|
- Gemfile
|
|
153
158
|
- MIT-LICENSE
|
|
154
159
|
- README.md
|
|
160
|
+
- RELEASING.md
|
|
155
161
|
- Rakefile
|
|
156
162
|
- autodiscover.gemspec
|
|
157
163
|
- lib/autodiscover.rb
|
|
@@ -169,9 +175,10 @@ files:
|
|
|
169
175
|
- test/units/pox_response_test.rb
|
|
170
176
|
- test/units/server_version_parser_test.rb
|
|
171
177
|
homepage: http://github.com/WinRb/autodiscover
|
|
172
|
-
licenses:
|
|
173
|
-
|
|
174
|
-
|
|
178
|
+
licenses:
|
|
179
|
+
- MIT
|
|
180
|
+
metadata:
|
|
181
|
+
rubygems_mfa_required: 'true'
|
|
175
182
|
rdoc_options: []
|
|
176
183
|
require_paths:
|
|
177
184
|
- lib
|
|
@@ -186,9 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
186
193
|
- !ruby/object:Gem::Version
|
|
187
194
|
version: '0'
|
|
188
195
|
requirements: []
|
|
189
|
-
|
|
190
|
-
rubygems_version: 2.5.1
|
|
191
|
-
signing_key:
|
|
196
|
+
rubygems_version: 3.6.9
|
|
192
197
|
specification_version: 4
|
|
193
198
|
summary: Ruby client for Microsoft's Autodiscover Service
|
|
194
199
|
test_files:
|
data/.travis.yml
DELETED
data/CHANGELOG
DELETED