mail_address 1.2.19 → 1.3.0
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 +4 -4
- data/.github/workflows/test.yml +27 -0
- data/CLAUDE.md +43 -0
- data/lib/mail_address/address.rb +13 -15
- data/lib/mail_address/mail_address.rb +11 -10
- data/lib/mail_address/simple_parser.rb +20 -21
- data/lib/mail_address/version.rb +1 -1
- data/lib/mail_address.rb +0 -1
- data/mail_address.gemspec +3 -4
- data/spec/spec_helper.rb +13 -8
- metadata +5 -4
- data/.travis.yml +0 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3ac1b18916f09e9ab8d6b774632f191f7eb3cc941df6e96267f4f72aec2fdfe5
|
|
4
|
+
data.tar.gz: 19ec24086e0f203ed3c9a18052d82acebd4831d968b25fdc5124ec8ed582302f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb6fecb18ae04b8aa664b870c1c90751ad612c6a78b216c6760df79565b652e5822dd6d29ee0586e47891aaaa8fd70925d38eb6177c0217491df3bf5673f253e
|
|
7
|
+
data.tar.gz: 81cd4080f262badace8c5254f91934b7086304f5977308c28461cf87156c47ff4dd65486ff1a78977204dbf33eab0ce9d48630da96bb8b31ce3d9e3dcad2bedc
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Test
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [master]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [master]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
fail-fast: false
|
|
14
|
+
matrix:
|
|
15
|
+
ruby-version: ['2.7', '3.0', '3.1', '3.2', '3.3']
|
|
16
|
+
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v4
|
|
19
|
+
|
|
20
|
+
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
21
|
+
uses: ruby/setup-ruby@v1
|
|
22
|
+
with:
|
|
23
|
+
ruby-version: ${{ matrix.ruby-version }}
|
|
24
|
+
bundler-cache: true
|
|
25
|
+
|
|
26
|
+
- name: Run tests
|
|
27
|
+
run: bundle exec rake spec
|
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
MailAddress は Perl の `Mail::Address` モジュールを Ruby に移植したメールアドレスパーサー gem。RFC非準拠のアドレス(docomo/au などの日本のキャリアメールで使われる `..` や末尾 `.`)もパース可能。ランタイム依存なし(Pure Ruby)。
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# テスト実行(デフォルトの rake タスク)
|
|
13
|
+
bundle exec rake spec
|
|
14
|
+
|
|
15
|
+
# 特定ファイルのテスト
|
|
16
|
+
bundle exec rspec spec/mail_address_spec.rb
|
|
17
|
+
|
|
18
|
+
# 特定行のテスト
|
|
19
|
+
bundle exec rspec spec/mail_address_spec.rb:10
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
リンターは未設定。
|
|
23
|
+
|
|
24
|
+
## Architecture
|
|
25
|
+
|
|
26
|
+
### コア構造
|
|
27
|
+
|
|
28
|
+
- **`lib/mail_address.rb`** — エントリポイント。`MailAddress.parse`, `MailAddress.parse_first`, `MailAddress.parse_simple` を提供
|
|
29
|
+
- **`lib/mail_address/address.rb`** — `MailAddress::Address` クラス。パース結果を保持(`phrase`, `address`, `original`)し、`name`, `host`, `user`, `format` メソッドを提供
|
|
30
|
+
- **`lib/mail_address/mail_address.rb`** — メインのパースロジック。トークン化と複雑なアドレスフォーマットの処理
|
|
31
|
+
- **`lib/mail_address/simple_parser.rb`** — Google Closure Library ベースのシンプルパーサー(スペース/カンマ区切りのアドレス向け)
|
|
32
|
+
|
|
33
|
+
### パース戦略
|
|
34
|
+
|
|
35
|
+
2つのパーサーを使い分ける:
|
|
36
|
+
- **メインパーサー** (`parse`) — RFC準拠・非準拠の複雑なフォーマットを処理。括弧コメント、クォート、MIME エンコードなどに対応
|
|
37
|
+
- **シンプルパーサー** (`parse_simple` / `g_parse`) — 空白・カンマ区切りの単純なリスト向け
|
|
38
|
+
|
|
39
|
+
### コーディング規約
|
|
40
|
+
|
|
41
|
+
- プライベートメソッドは `_` プレフィックス(例: `_tokenize`, `_complete`)
|
|
42
|
+
- 定数は `UPPER_CASE`
|
|
43
|
+
- テストは RSpec 3 の `expect` 構文を使用
|
data/lib/mail_address/address.rb
CHANGED
|
@@ -27,7 +27,7 @@ module MailAddress
|
|
|
27
27
|
|
|
28
28
|
email_address = enquote ? quoted_address : @address
|
|
29
29
|
|
|
30
|
-
if !@phrase.nil? &&
|
|
30
|
+
if !@phrase.nil? && !@phrase.empty?
|
|
31
31
|
# if @phrase.match(/\A\(/) && @phrase.match(/\)\z/)
|
|
32
32
|
# addr.push(email_address) if !@address.nil? && @address.length > 0
|
|
33
33
|
# addr.push(@phrase)
|
|
@@ -35,11 +35,11 @@ module MailAddress
|
|
|
35
35
|
addr.push(
|
|
36
36
|
@phrase.match(/^(?:#{ATEXT})+$/) ? @phrase
|
|
37
37
|
: @phrase.match(/(?<!\\)"/) ? @phrase
|
|
38
|
-
:
|
|
38
|
+
: "\"#{@phrase}\""
|
|
39
39
|
)
|
|
40
|
-
addr.push "<#{email_address}>" if !@address.nil? &&
|
|
40
|
+
addr.push "<#{email_address}>" if !@address.nil? && !@address.empty?
|
|
41
41
|
# end
|
|
42
|
-
elsif !@address.nil? &&
|
|
42
|
+
elsif !@address.nil? && !@address.empty?
|
|
43
43
|
addr.push(email_address)
|
|
44
44
|
end
|
|
45
45
|
addr.join(' ')
|
|
@@ -48,19 +48,19 @@ module MailAddress
|
|
|
48
48
|
def name
|
|
49
49
|
phrase = @phrase.dup
|
|
50
50
|
name = Address._extract_name(phrase)
|
|
51
|
-
name.
|
|
51
|
+
!name.empty? ? name : nil
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def host
|
|
55
|
-
addr = @address || ''
|
|
55
|
+
addr = @address || ''
|
|
56
56
|
i = addr.rindex('@')
|
|
57
|
-
|
|
57
|
+
addr[(i + 1)..] if i
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def user
|
|
61
|
-
addr = @address || ''
|
|
61
|
+
addr = @address || ''
|
|
62
62
|
i = addr.rindex('@')
|
|
63
|
-
i
|
|
63
|
+
i ? addr[0...i] : addr
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def quoted_address
|
|
@@ -78,18 +78,16 @@ module MailAddress
|
|
|
78
78
|
# given a comment, attempt to extract a person's name
|
|
79
79
|
def self._extract_name(name)
|
|
80
80
|
# This function can be called as method as well
|
|
81
|
-
return '' if name.nil? || name
|
|
81
|
+
return '' if name.nil? || name.empty?
|
|
82
82
|
|
|
83
83
|
# Using encodings, too hard. See Mail::Message::Field::Full.
|
|
84
|
-
return '' if name.match(/\=\?.*?\?\=/)
|
|
84
|
+
return '' if name.match?(/\=\?.*?\?\=/)
|
|
85
85
|
|
|
86
86
|
# trim whitespace
|
|
87
|
-
name.
|
|
88
|
-
name.sub!(/\s+$/, '')
|
|
89
|
-
name.sub!(/\s+/, ' ')
|
|
87
|
+
name = name.strip.gsub(/\s+/, ' ')
|
|
90
88
|
|
|
91
89
|
# Disregard numeric names (e.g. 123456.1234@compuserve.com)
|
|
92
|
-
return
|
|
90
|
+
return '' if name.match?(/^[\d ]+$/)
|
|
93
91
|
|
|
94
92
|
name.sub!(/^\((.*)\)$/, '\1') # remove outermost parenthesis
|
|
95
93
|
name.sub!(/^"(.*)"$/, '\1') # remove outer quotation marks
|
|
@@ -10,12 +10,12 @@ module MailAddress
|
|
|
10
10
|
line = lines.join('').strip
|
|
11
11
|
|
|
12
12
|
# empty or <> or < or >
|
|
13
|
-
if line.empty? || line.match(/\A[<>;, \\]+\z/)
|
|
13
|
+
if line.empty? || line.match?(/\A[<>;, \\]+\z/)
|
|
14
14
|
return [ MailAddress::Address.new(line, nil, line) ]
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
# undisclosed-recipient
|
|
18
|
-
if line.match(/undisclosed[ \-]recipients?: ?;?/i)
|
|
18
|
+
if line.match?(/undisclosed[ \-]recipients?: ?;?/i)
|
|
19
19
|
return [ MailAddress::Address.new(line, nil, line) ]
|
|
20
20
|
end
|
|
21
21
|
|
|
@@ -27,7 +27,7 @@ module MailAddress
|
|
|
27
27
|
len = tokens.length
|
|
28
28
|
_next = _find_next idx, tokens, len
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
(0...len).each do |idx|
|
|
31
31
|
|
|
32
32
|
token = tokens[idx]
|
|
33
33
|
substr = token[0, 1]
|
|
@@ -55,7 +55,8 @@ module MailAddress
|
|
|
55
55
|
if depth > 0
|
|
56
56
|
# raise "Unmatched '<>' in line"
|
|
57
57
|
o = MailAddress::Address.new(original, nil, original)
|
|
58
|
-
phrase.clear
|
|
58
|
+
phrase.clear
|
|
59
|
+
address.clear
|
|
59
60
|
else
|
|
60
61
|
o = _complete(phrase, address, original)
|
|
61
62
|
end
|
|
@@ -70,7 +71,7 @@ module MailAddress
|
|
|
70
71
|
address.push(token)
|
|
71
72
|
elsif (_next == '<')
|
|
72
73
|
phrase.push(token)
|
|
73
|
-
elsif ( token.match(/^[.\@:;]/) || address.empty? || address[-1].match(/^[.\@:;]/) )
|
|
74
|
+
elsif ( token.match?(/^[.\@:;]/) || address.empty? || address[-1].match?(/^[.\@:;]/) )
|
|
74
75
|
token.strip!
|
|
75
76
|
address.push(token)
|
|
76
77
|
else
|
|
@@ -90,10 +91,9 @@ module MailAddress
|
|
|
90
91
|
line.sub!(/\A\s+/, '')
|
|
91
92
|
line.gsub!(/[\r\n]+/,' ')
|
|
92
93
|
|
|
93
|
-
|
|
94
|
-
tmp = nil
|
|
94
|
+
until line.empty?
|
|
95
95
|
if (
|
|
96
|
-
line.match(/"[^"]+"/) && line.sub!(/\A(\\?"(?:[^"\\]+|\\.)*")(\s*)/, '') || # "..."
|
|
96
|
+
line.match?(/"[^"]+"/) && line.sub!(/\A(\\?"(?:[^"\\]+|\\.)*")(\s*)/, '') || # "..."
|
|
97
97
|
line.sub!(/\A([^\s()<>\@,;:\\".\[\]]+)(\s*)/, '') ||
|
|
98
98
|
line.sub!(/\A([()<>\@,;:\\".\[\]])(\s*)/, '')
|
|
99
99
|
)
|
|
@@ -127,7 +127,7 @@ module MailAddress
|
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
def self._complete (phrase, address, original)
|
|
130
|
-
phrase.
|
|
130
|
+
return nil if phrase.empty? && address.empty?
|
|
131
131
|
|
|
132
132
|
name = phrase.join('').strip
|
|
133
133
|
|
|
@@ -140,7 +140,8 @@ module MailAddress
|
|
|
140
140
|
name = name.gsub(ESCAPED_BACKSLASHES_, '\\')
|
|
141
141
|
|
|
142
142
|
new_address = MailAddress::Address.new(name, address.join(''), original)
|
|
143
|
-
phrase.clear
|
|
143
|
+
phrase.clear
|
|
144
|
+
address.clear
|
|
144
145
|
new_address
|
|
145
146
|
end
|
|
146
147
|
|
|
@@ -12,10 +12,10 @@ module MailAddress
|
|
|
12
12
|
# CHARS_REQUIRE_QUOTES_ = SPECIAL_CHARS + ADDRESS_SEPARATORS_
|
|
13
13
|
ESCAPED_DOUBLE_QUOTES_ = /\\\"/
|
|
14
14
|
ESCAPED_BACKSLASHES_ = /\\\\/
|
|
15
|
-
QUOTED_REGEX_STR_ = '[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}
|
|
15
|
+
QUOTED_REGEX_STR_ = '[+a-zA-Z0-9_.!#$%&\'*\\/=?^`{|}~\-]+'
|
|
16
16
|
UNQUOTED_REGEX_STR_ = '"' + QUOTED_REGEX_STR_ + '"'
|
|
17
17
|
LOCAL_PART_REGEXP_STR_ = '(?:' + QUOTED_REGEX_STR_ + '|' + UNQUOTED_REGEX_STR_ + ')'
|
|
18
|
-
DOMAIN_PART_REGEXP_STR_ = '([a-zA-Z0-9
|
|
18
|
+
DOMAIN_PART_REGEXP_STR_ = '([a-zA-Z0-9\-_]+\\.)+[a-zA-Z0-9]{2,63}'
|
|
19
19
|
EMAIL_ADDRESS_ = Regexp.new('\\A' + LOCAL_PART_REGEXP_STR_ + '@' + DOMAIN_PART_REGEXP_STR_ + '\\z')
|
|
20
20
|
|
|
21
21
|
def self.parse_simple(str)
|
|
@@ -25,13 +25,13 @@ module MailAddress
|
|
|
25
25
|
# Remove non-UNIX-style newlines that would otherwise cause getToken_ to
|
|
26
26
|
# choke. Remove multiple consecutive whitespace characters for the same
|
|
27
27
|
# reason.
|
|
28
|
-
str =
|
|
28
|
+
str = collapse_whitespace(str)
|
|
29
29
|
i = 0
|
|
30
|
-
while
|
|
30
|
+
while i < str.length
|
|
31
31
|
token = get_token(str, i)
|
|
32
|
-
if
|
|
33
|
-
if !
|
|
34
|
-
result.push(
|
|
32
|
+
if is_address_separator(token) || (token == ' ' && is_valid(parse_internal(email)))
|
|
33
|
+
if !is_empty_or_whitespace(email)
|
|
34
|
+
result.push(parse_internal(email))
|
|
35
35
|
end
|
|
36
36
|
email = ''
|
|
37
37
|
i += 1
|
|
@@ -42,34 +42,34 @@ module MailAddress
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
# Add the final token.
|
|
45
|
-
if
|
|
46
|
-
result.push(
|
|
45
|
+
if !is_empty_or_whitespace(email)
|
|
46
|
+
result.push(parse_internal(email))
|
|
47
47
|
end
|
|
48
|
-
|
|
48
|
+
result
|
|
49
49
|
end
|
|
50
50
|
|
|
51
51
|
def self.parse_internal(addr)
|
|
52
52
|
name = ''
|
|
53
53
|
address = ''
|
|
54
54
|
i = 0
|
|
55
|
-
while
|
|
55
|
+
while i < addr.length
|
|
56
56
|
token = get_token(addr, i)
|
|
57
|
-
if
|
|
57
|
+
if token[0] == '<' && token.index('>')
|
|
58
58
|
end_i = token.index('>')
|
|
59
59
|
address = token[1, end_i - 1]
|
|
60
|
-
elsif
|
|
60
|
+
elsif address == ''
|
|
61
61
|
name << token
|
|
62
62
|
end
|
|
63
63
|
i += token.length
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
# Check if it's a simple email address of the form "jlim@google.com".
|
|
67
|
-
if
|
|
67
|
+
if address == '' && name.index('@')
|
|
68
68
|
address = name
|
|
69
69
|
name = ''
|
|
70
70
|
end
|
|
71
71
|
|
|
72
|
-
name =
|
|
72
|
+
name = collapse_whitespace(name)
|
|
73
73
|
name = name[1 .. -2] if name.start_with?('\'') && name.end_with?('\'')
|
|
74
74
|
name = name[1 .. -2] if name.start_with?('"') && name.end_with?('"')
|
|
75
75
|
|
|
@@ -89,7 +89,7 @@ module MailAddress
|
|
|
89
89
|
p = OPENERS_.index(ch)
|
|
90
90
|
return ch unless p
|
|
91
91
|
|
|
92
|
-
if
|
|
92
|
+
if is_escaped_dbl_quote(str, pos)
|
|
93
93
|
# If an opener is an escaped quote we do not treat it as a real opener
|
|
94
94
|
# and keep accumulating the token.
|
|
95
95
|
return ch
|
|
@@ -99,19 +99,18 @@ module MailAddress
|
|
|
99
99
|
|
|
100
100
|
# If the closer is a quote we go forward skipping escaped quotes until we
|
|
101
101
|
# hit the real closing one.
|
|
102
|
-
while
|
|
102
|
+
while end_pos && end_pos >= 0 && is_escaped_dbl_quote(str, end_pos)
|
|
103
103
|
end_pos = str.index(closer_char, end_pos + 1)
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
|
|
107
|
-
return token
|
|
106
|
+
(end_pos && end_pos >= 0) ? str[pos .. end_pos] : ch
|
|
108
107
|
end
|
|
109
108
|
|
|
110
109
|
def self.is_escaped_dbl_quote(str, pos)
|
|
111
110
|
return false if str[pos] != '"'
|
|
112
111
|
slash_count = 0
|
|
113
112
|
|
|
114
|
-
|
|
113
|
+
(pos - 1).downto(0) do |idx|
|
|
115
114
|
break unless str[idx] == '\\'
|
|
116
115
|
slash_count += 1
|
|
117
116
|
end
|
|
@@ -123,7 +122,7 @@ module MailAddress
|
|
|
123
122
|
end
|
|
124
123
|
|
|
125
124
|
def self.is_empty_or_whitespace(str)
|
|
126
|
-
/\A[\s\xc2\xa0]*\z/
|
|
125
|
+
str.match?(/\A[\s\xc2\xa0]*\z/)
|
|
127
126
|
end
|
|
128
127
|
|
|
129
128
|
def self.is_address_separator(ch)
|
data/lib/mail_address/version.rb
CHANGED
data/lib/mail_address.rb
CHANGED
data/mail_address.gemspec
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
|
1
|
+
lib = File.expand_path('lib', __dir__)
|
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
3
|
require 'mail_address/version'
|
|
5
4
|
|
|
@@ -8,8 +7,8 @@ Gem::Specification.new do |spec|
|
|
|
8
7
|
spec.version = MailAddress::VERSION
|
|
9
8
|
spec.authors = ["Kizashi Nagata"]
|
|
10
9
|
spec.email = ["kizashi1122@gmail.com"]
|
|
11
|
-
spec.summary =
|
|
12
|
-
spec.description =
|
|
10
|
+
spec.summary = "Simple Mail Address Parser"
|
|
11
|
+
spec.description = "A practical mail address parser implemented based on Perl Module Mail::Address."
|
|
13
12
|
spec.homepage = "https://github.com/kizashi1122/mail_address"
|
|
14
13
|
spec.license = "MIT"
|
|
15
14
|
|
data/spec/spec_helper.rb
CHANGED
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
require 'simplecov'
|
|
2
|
-
require 'coveralls'
|
|
3
|
-
Coveralls.wear!
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Coveralls
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
begin
|
|
4
|
+
require 'coveralls'
|
|
5
|
+
Coveralls.wear! do
|
|
6
|
+
add_filter '.bundle/'
|
|
7
|
+
end
|
|
8
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
|
9
|
+
SimpleCov::Formatter::HTMLFormatter,
|
|
10
|
+
Coveralls::SimpleCov::Formatter
|
|
11
|
+
])
|
|
12
|
+
rescue LoadError
|
|
13
|
+
SimpleCov.start do
|
|
14
|
+
add_filter '.bundle/'
|
|
15
|
+
end
|
|
11
16
|
end
|
|
12
17
|
|
|
13
18
|
require 'rubygems'
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mail_address
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kizashi Nagata
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-02-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -80,9 +80,10 @@ extensions: []
|
|
|
80
80
|
extra_rdoc_files: []
|
|
81
81
|
files:
|
|
82
82
|
- ".coveralls.yml"
|
|
83
|
+
- ".github/workflows/test.yml"
|
|
83
84
|
- ".gitignore"
|
|
84
85
|
- ".rspec"
|
|
85
|
-
-
|
|
86
|
+
- CLAUDE.md
|
|
86
87
|
- Gemfile
|
|
87
88
|
- LICENSE.txt
|
|
88
89
|
- README.md
|
|
@@ -116,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
116
117
|
- !ruby/object:Gem::Version
|
|
117
118
|
version: '0'
|
|
118
119
|
requirements: []
|
|
119
|
-
rubygems_version: 3.1.
|
|
120
|
+
rubygems_version: 3.1.6
|
|
120
121
|
signing_key:
|
|
121
122
|
specification_version: 4
|
|
122
123
|
summary: Simple Mail Address Parser
|
data/.travis.yml
DELETED