validators 3.2.1 → 3.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.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +3 -0
  4. data/README.md +4 -4
  5. data/bin/sync-disposable-hostnames +120 -110
  6. data/bin/sync-tld +2 -2
  7. data/data/country_tlds.txt +235 -0
  8. data/data/disposable_domains.txt +110996 -0
  9. data/data/disposable_emails.txt +38 -0
  10. data/data/reserved_subdomains.txt +2830 -0
  11. data/data/tld.txt +1508 -0
  12. data/lib/validators.rb +1 -0
  13. data/lib/validators/constants.rb +1 -1
  14. data/lib/validators/disposable_emails.rb +19 -0
  15. data/lib/validators/disposable_hostnames.rb +2 -2
  16. data/lib/validators/locale/en.yml +2 -1
  17. data/lib/validators/locale/pt-BR.yml +1 -0
  18. data/lib/validators/reserved_subdomains.rb +2 -4
  19. data/lib/validators/tld.rb +2 -2
  20. data/lib/validators/validates_email_format_of.rb +19 -4
  21. data/lib/validators/version.rb +2 -2
  22. data/test/test_helper.rb +17 -1
  23. data/test/validators/disposable_email_test.rb +18 -5
  24. data/test/validators/validates_email_format_of_test.rb +4 -2
  25. data/validators.gemspec +3 -0
  26. metadata +53 -43
  27. data/data/country_tlds.json +0 -237
  28. data/data/disposable.json +0 -128
  29. data/data/disposable/10minutemail.json +0 -3
  30. data/data/disposable/1secmail.json +0 -5
  31. data/data/disposable/FGRibreau_mailchecker.json +0 -33602
  32. data/data/disposable/andreis_disposable_email_domains.json +0 -48320
  33. data/data/disposable/clipmails.json +0 -27
  34. data/data/disposable/cs.json +0 -15
  35. data/data/disposable/emailfake.json +0 -128
  36. data/data/disposable/fake_email_generator.json +0 -11
  37. data/data/disposable/fnando_dafe542cac13f831bbf5521a55248116.json +0 -20
  38. data/data/disposable/gmailnator.json +0 -3
  39. data/data/disposable/guerrillamail.json +0 -13
  40. data/data/disposable/ically.json +0 -28
  41. data/data/disposable/itemp.json +0 -4
  42. data/data/disposable/ivolo_disposable_email_domains.json +0 -48177
  43. data/data/disposable/jespernissen_disposable_maildomain_list.json +0 -2372
  44. data/data/disposable/maxmalysh_disposable_emails.json +0 -21372
  45. data/data/disposable/moakt.json +0 -12
  46. data/data/disposable/receivemail.json +0 -9
  47. data/data/disposable/sneakykiwi_LeagueCreatorPublic.json +0 -2364
  48. data/data/disposable/tempemail.json +0 -7
  49. data/data/disposable/tempemails.json +0 -10
  50. data/data/disposable/tempmail.json +0 -31
  51. data/data/disposable/tempmail_io.json +0 -8
  52. data/data/disposable/tempmailaddress.json +0 -4
  53. data/data/disposable/tempomail.json +0 -3
  54. data/data/disposable/tempr.json +0 -97
  55. data/data/disposable/tmail.json +0 -3
  56. data/data/disposable/wesbos_burner_email_providers.json +0 -4711
  57. data/data/disposable/willwhite_freemail.json +0 -352
  58. data/data/disposable/yepmail.json +0 -12
  59. data/data/disposable_emails.json +0 -3
  60. data/data/disposable_patterns.json +0 -3
  61. data/data/disposable_raw.json +0 -128
  62. data/data/reserved_subdomains.json +0 -2838
  63. data/data/sld.json +0 -5564
  64. data/data/tld.json +0 -1518
@@ -8,6 +8,7 @@ module Validators
8
8
  require "validators/tld"
9
9
  require "validators/hostname"
10
10
  require "validators/disposable_hostnames"
11
+ require "validators/disposable_emails"
11
12
  require "validators/reserved_subdomains"
12
13
 
13
14
  require "validators/validates_datetime"
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Validators
4
4
  EMAIL_FORMAT = /\A[a-z0-9]+([-._][a-z0-9]+)*(\+[^@]+)?@[a-z0-9]+([.-][a-z0-9]+)*\.[a-z]{2,}\z/i.freeze
5
- MICROSOFT_EMAIL_FORMAT = /\A[\w][\w\d._-]*[\w\d_-]+(\+[\w\d]+)?@(hotmail|outlook).com\z/i.freeze
5
+ MICROSOFT_EMAIL_FORMAT = /\A[a-z0-9][a-z0-9._-]*[a-z0-9_-]+(\+[a-z0-9]+)?@(hotmail|outlook).com\z/i.freeze
6
6
 
7
7
  # Source: https://github.com/henrik/validates_url_format_of
8
8
  IPV4_PART = /\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]/.freeze # 0-255
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Validators
4
+ class DisposableEmails
5
+ FILE_PATH = File.expand_path("../../data/disposable_emails.txt", __dir__)
6
+
7
+ def self.all
8
+ @all ||= File.read(FILE_PATH).lines.map(&:chomp)
9
+ end
10
+
11
+ def self.include?(email)
12
+ mailbox, domain = email.to_s.split("@")
13
+ mailbox = mailbox.to_s.gsub(".", "")
14
+ mailbox = mailbox.gsub(/\+(.+)?\Z/, "")
15
+
16
+ all.include?("#{mailbox}@#{domain}")
17
+ end
18
+ end
19
+ end
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Validators
4
4
  class DisposableHostnames
5
- FILE_PATH = File.expand_path("../../data/disposable.json", __dir__)
5
+ FILE_PATH = File.expand_path("../../data/disposable_domains.txt", __dir__)
6
6
 
7
7
  def self.all
8
- @all ||= JSON.parse(File.read(FILE_PATH))
8
+ @all ||= File.read(FILE_PATH).lines.map(&:chomp)
9
9
  end
10
10
  end
11
11
  end
@@ -3,7 +3,8 @@ en:
3
3
  activemodel: &activemodel
4
4
  errors:
5
5
  messages:
6
- disposable_email: "is not allowed (high-bounce domain)"
6
+ disposable_email: "is not allowed (high-bounce email)"
7
+ disposable_domain: "is not allowed (high-bounce domain)"
7
8
  invalid_cnpj: "is not a valid CNPJ"
8
9
  invalid_cpf: "is not a valid CPF"
9
10
  invalid_date: "is not a valid date"
@@ -4,6 +4,7 @@ pt-BR:
4
4
  errors:
5
5
  messages:
6
6
  disposable_email: "não é permitido (e-mail temporário)"
7
+ disposable_domain: "não é permitido (e-mail temporário)"
7
8
  invalid_cnpj: "não é um CNPJ válido"
8
9
  invalid_cpf: "não é um CPF válido"
9
10
  invalid_date: "não é uma data válida"
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Validators
4
4
  class ReservedSubdomains
5
- FILE_PATH = File.expand_path("../../data/reserved_subdomains.json", __dir__)
5
+ FILE_PATH = File.expand_path("../../data/reserved_subdomains.txt", __dir__)
6
6
 
7
7
  def self.reserved?(hostname, matchers = nil)
8
8
  matchers = parse_list(matchers) if matchers
@@ -11,9 +11,7 @@ module Validators
11
11
  end
12
12
 
13
13
  def self.all
14
- @all ||= JSON
15
- .parse(File.read(FILE_PATH))
16
- .map {|matcher| parse(matcher) }
14
+ @all ||= File.read(FILE_PATH).lines.map {|matcher| parse(matcher.chomp) }
17
15
  end
18
16
 
19
17
  def self.parse(matcher)
@@ -2,10 +2,10 @@
2
2
 
3
3
  module Validators
4
4
  class TLD
5
- FILE_PATH = File.expand_path("../../data/tld.json", __dir__)
5
+ FILE_PATH = File.expand_path("../../data/tld.txt", __dir__)
6
6
 
7
7
  def self.all
8
- @all ||= JSON.parse(File.read(FILE_PATH))
8
+ @all ||= File.read(FILE_PATH).lines.map(&:chomp)
9
9
  end
10
10
 
11
11
  def self.host_with_valid_tld?(host)
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "root_domain"
4
+
3
5
  module ActiveModel
4
6
  module Validations
5
7
  class EmailValidator < EachValidator
@@ -14,6 +16,7 @@ module ActiveModel
14
16
 
15
17
  validate_tld(record, attribute, value, options) if check_tld
16
18
  validate_email_format(record, attribute, value, options)
19
+ validate_disposable_domain(record, attribute, value, options) unless allow_disposable
17
20
  validate_disposable_email(record, attribute, value, options) unless allow_disposable
18
21
  end
19
22
 
@@ -41,12 +44,24 @@ module ActiveModel
41
44
  )
42
45
  end
43
46
 
44
- def validate_disposable_email(record, attribute, value, _options)
47
+ def validate_disposable_domain(record, attribute, value, _options)
48
+ return unless value
49
+
45
50
  hostname = value.to_s.split(AT_SIGN).last.to_s.downcase
51
+ root_domain = RootDomain.call(hostname)
46
52
 
47
- return if Validators::DisposableHostnames.all.none? do |disposable_hostname|
48
- hostname == disposable_hostname || hostname.end_with?(".#{disposable_hostname}")
49
- end
53
+ return unless Validators::DisposableHostnames.all.include?(root_domain)
54
+
55
+ record.errors.add(
56
+ attribute,
57
+ :disposable_domain,
58
+ value: value
59
+ )
60
+ end
61
+
62
+ def validate_disposable_email(record, attribute, value, _options)
63
+ return unless value
64
+ return unless Validators::DisposableEmails.include?(value)
50
65
 
51
66
  record.errors.add(
52
67
  attribute,
@@ -3,8 +3,8 @@
3
3
  module Validators
4
4
  module Version
5
5
  MAJOR = 3
6
- MINOR = 2
7
- PATCH = 1
6
+ MINOR = 3
7
+ PATCH = 0
8
8
  STRING = "#{MAJOR}.#{MINOR}.#{PATCH}"
9
9
  end
10
10
  end
@@ -17,9 +17,25 @@ require "active_support/all"
17
17
  require "minitest/utils"
18
18
  require "minitest/autorun"
19
19
 
20
+ def build_email_with_filter(email)
21
+ mailbox, domain = email.split("@")
22
+ "#{mailbox}+#{SecureRandom.hex(3)}@#{domain}"
23
+ end
24
+
25
+ def build_email_with_dots(email)
26
+ mailbox, domain = email.split("@")
27
+ new_mailbox = mailbox.chars.map {|char| [char, "."] }.flatten[0..-2].join
28
+
29
+ "#{new_mailbox}@#{domain}"
30
+ end
31
+
20
32
  Time.zone = "America/Sao_Paulo"
21
33
  TLDs = Validators::TLD.all.sample(10)
22
- DISPOSABLE_EMAILS = Validators::DisposableHostnames.all.sample(10)
34
+ DISPOSABLE_DOMAINS = Validators::DisposableHostnames.all.sample(10)
35
+ DISPOSABLE_EMAILS = Validators::DisposableEmails.all +
36
+ Validators::DisposableEmails.all.sample(10).map {|email| build_email_with_filter(email) } +
37
+ Validators::DisposableEmails.all.sample(10).map {|email| build_email_with_dots(email) } +
38
+ Validators::DisposableEmails.all.sample(10).map {|email| build_email_with_filter(build_email_with_dots(email)) }
23
39
 
24
40
  Dir[File.join(__dir__, "support/**/*.rb")].sort.each {|f| require f }
25
41
 
@@ -3,18 +3,19 @@
3
3
  require "test_helper"
4
4
 
5
5
  class DisposableEmailTest < Minitest::Test
6
- DISPOSABLE_EMAILS.each do |domain|
7
- test "rejects disposable e-mail (#{domain})" do
6
+ DISPOSABLE_DOMAINS.each do |domain|
7
+ test "rejects disposable domain (#{domain})" do
8
8
  User.validates_email_format_of :email
9
9
 
10
10
  user = User.new(email: "user@#{domain}")
11
11
  user.valid?
12
12
 
13
- assert_includes user.errors[:email], I18n.t("activerecord.errors.messages.disposable_email")
13
+ assert_includes user.errors[:email],
14
+ I18n.t("activerecord.errors.messages.disposable_domain")
14
15
  end
15
16
  end
16
17
 
17
- DISPOSABLE_EMAILS.each do |domain|
18
+ DISPOSABLE_DOMAINS.each do |domain|
18
19
  test "rejects disposable e-mail with subdomain (custom.#{domain})" do
19
20
  User.validates_email_format_of :email
20
21
 
@@ -22,7 +23,7 @@ class DisposableEmailTest < Minitest::Test
22
23
  user.valid?
23
24
 
24
25
  assert_includes user.errors[:email],
25
- "is not allowed (high-bounce domain)"
26
+ I18n.t("activerecord.errors.messages.disposable_domain")
26
27
  end
27
28
  end
28
29
 
@@ -34,4 +35,16 @@ class DisposableEmailTest < Minitest::Test
34
35
 
35
36
  assert user.errors[:email].empty?
36
37
  end
38
+
39
+ DISPOSABLE_EMAILS.each do |email|
40
+ test "rejects disposable e-mail (#{email})" do
41
+ User.validates_email_format_of :email
42
+
43
+ user = User.new(email: email)
44
+ user.valid?
45
+
46
+ assert_includes user.errors[:email],
47
+ I18n.t("activerecord.errors.messages.disposable_email")
48
+ end
49
+ end
37
50
  end
@@ -12,10 +12,12 @@ class ValidatesEmailFormatOfTest < Minitest::Test
12
12
  VALID_EMAILS.each do |email|
13
13
  test "accepts #{email.inspect} as a valid email" do
14
14
  user = User.new(email: email, corporate_email: email)
15
- assert user.valid?
15
+ user.valid?
16
+ assert_empty user.errors
16
17
 
17
18
  user = Person.new(email: email)
18
- assert user.valid?
19
+ user.valid?
20
+ assert_empty user.errors
19
21
  end
20
22
  end
21
23
 
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_development_dependency "nokogiri"
29
29
  s.add_development_dependency "pry-meta"
30
30
  s.add_development_dependency "rake"
31
+ s.add_development_dependency "root_domain"
31
32
  s.add_development_dependency "rubocop"
32
33
  s.add_development_dependency "rubocop-fnando"
33
34
  s.add_development_dependency "simplecov"
@@ -35,4 +36,6 @@ Gem::Specification.new do |s|
35
36
  s.add_development_dependency "simpleidn"
36
37
  s.add_development_dependency "sqlite3", "~> 1.4"
37
38
  s.add_development_dependency "sshkey"
39
+ s.add_development_dependency "whois"
40
+ s.add_development_dependency "whois-parser"
38
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: validators
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.1
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-10 00:00:00.000000000 Z
11
+ date: 2020-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
124
  version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: root_domain
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  - !ruby/object:Gem::Dependency
126
140
  name: rubocop
127
141
  requirement: !ruby/object:Gem::Requirement
@@ -220,6 +234,34 @@ dependencies:
220
234
  - - ">="
221
235
  - !ruby/object:Gem::Version
222
236
  version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: whois
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ">="
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ">="
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: whois-parser
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ">="
256
+ - !ruby/object:Gem::Version
257
+ version: '0'
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ">="
263
+ - !ruby/object:Gem::Version
264
+ version: '0'
223
265
  description: Add some nice ActiveModel/ActiveRecord validators.
224
266
  email:
225
267
  - fnando.vieira@gmail.com
@@ -237,46 +279,14 @@ files:
237
279
  - Rakefile
238
280
  - bin/sync-disposable-hostnames
239
281
  - bin/sync-tld
240
- - data/country_tlds.json
241
- - data/disposable.json
242
- - data/disposable/10minutemail.json
243
- - data/disposable/1secmail.json
244
- - data/disposable/FGRibreau_mailchecker.json
245
- - data/disposable/andreis_disposable_email_domains.json
246
- - data/disposable/clipmails.json
247
- - data/disposable/cs.json
248
- - data/disposable/emailfake.json
249
- - data/disposable/fake_email_generator.json
250
- - data/disposable/fnando_dafe542cac13f831bbf5521a55248116.json
251
- - data/disposable/gmailnator.json
252
- - data/disposable/guerrillamail.json
253
- - data/disposable/ically.json
254
- - data/disposable/itemp.json
255
- - data/disposable/ivolo_disposable_email_domains.json
256
- - data/disposable/jespernissen_disposable_maildomain_list.json
257
- - data/disposable/maxmalysh_disposable_emails.json
258
- - data/disposable/moakt.json
259
- - data/disposable/receivemail.json
260
- - data/disposable/sneakykiwi_LeagueCreatorPublic.json
261
- - data/disposable/tempemail.json
262
- - data/disposable/tempemails.json
263
- - data/disposable/tempmail.json
264
- - data/disposable/tempmail_io.json
265
- - data/disposable/tempmailaddress.json
266
- - data/disposable/tempomail.json
267
- - data/disposable/tempr.json
268
- - data/disposable/tmail.json
269
- - data/disposable/wesbos_burner_email_providers.json
270
- - data/disposable/willwhite_freemail.json
271
- - data/disposable/yepmail.json
272
- - data/disposable_emails.json
273
- - data/disposable_patterns.json
274
- - data/disposable_raw.json
275
- - data/reserved_subdomains.json
276
- - data/sld.json
277
- - data/tld.json
282
+ - data/country_tlds.txt
283
+ - data/disposable_domains.txt
284
+ - data/disposable_emails.txt
285
+ - data/reserved_subdomains.txt
286
+ - data/tld.txt
278
287
  - lib/validators.rb
279
288
  - lib/validators/constants.rb
289
+ - lib/validators/disposable_emails.rb
280
290
  - lib/validators/disposable_hostnames.rb
281
291
  - lib/validators/hostname.rb
282
292
  - lib/validators/ip.rb
@@ -333,7 +343,7 @@ homepage: http://rubygems.org/gems/validators
333
343
  licenses:
334
344
  - MIT
335
345
  metadata: {}
336
- post_install_message:
346
+ post_install_message:
337
347
  rdoc_options: []
338
348
  require_paths:
339
349
  - lib
@@ -349,7 +359,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
349
359
  version: '0'
350
360
  requirements: []
351
361
  rubygems_version: 3.1.2
352
- signing_key:
362
+ signing_key:
353
363
  specification_version: 4
354
364
  summary: Add some nice ActiveModel/ActiveRecord validators.
355
365
  test_files:
@@ -1,237 +0,0 @@
1
- [
2
- "ad",
3
- "ae",
4
- "af",
5
- "ag",
6
- "ai",
7
- "al",
8
- "am",
9
- "an",
10
- "ao",
11
- "aq",
12
- "ar",
13
- "as",
14
- "at",
15
- "au",
16
- "aw",
17
- "az",
18
- "ba",
19
- "bb",
20
- "bd",
21
- "be",
22
- "bf",
23
- "bg",
24
- "bh",
25
- "bi",
26
- "bj",
27
- "bm",
28
- "bn",
29
- "bo",
30
- "br",
31
- "bs",
32
- "bt",
33
- "bv",
34
- "bw",
35
- "by",
36
- "bz",
37
- "ca",
38
- "cc",
39
- "cd",
40
- "cf",
41
- "cg",
42
- "ch",
43
- "ci",
44
- "ck",
45
- "cl",
46
- "cm",
47
- "cn",
48
- "co",
49
- "cr",
50
- "cu",
51
- "cv",
52
- "cx",
53
- "cy",
54
- "cz",
55
- "de",
56
- "dj",
57
- "dk",
58
- "dm",
59
- "do",
60
- "dz",
61
- "ec",
62
- "ee",
63
- "eg",
64
- "eh",
65
- "er",
66
- "es",
67
- "et",
68
- "fi",
69
- "fj",
70
- "fk",
71
- "fr",
72
- "ga",
73
- "gb",
74
- "gd",
75
- "ge",
76
- "gf",
77
- "gh",
78
- "gi",
79
- "gl",
80
- "gm",
81
- "gn",
82
- "gp",
83
- "gq",
84
- "gr",
85
- "gs",
86
- "gt",
87
- "gu",
88
- "gw",
89
- "gy",
90
- "hk",
91
- "hm",
92
- "hn",
93
- "hr",
94
- "ht",
95
- "hu",
96
- "id",
97
- "ie",
98
- "il",
99
- "in",
100
- "io",
101
- "iq",
102
- "ir",
103
- "is",
104
- "it",
105
- "jm",
106
- "jo",
107
- "jp",
108
- "ke",
109
- "kg",
110
- "kh",
111
- "ki",
112
- "km",
113
- "kn",
114
- "kp",
115
- "kr",
116
- "kw",
117
- "ky",
118
- "kz",
119
- "la",
120
- "lb",
121
- "lc",
122
- "li",
123
- "lk",
124
- "lr",
125
- "ls",
126
- "lt",
127
- "lu",
128
- "lv",
129
- "ly",
130
- "ma",
131
- "mc",
132
- "md",
133
- "mg",
134
- "mh",
135
- "mk",
136
- "ml",
137
- "mm",
138
- "mn",
139
- "mo",
140
- "mp",
141
- "mq",
142
- "mr",
143
- "ms",
144
- "mt",
145
- "mu",
146
- "mv",
147
- "mw",
148
- "mx",
149
- "my",
150
- "mz",
151
- "na",
152
- "nc",
153
- "ne",
154
- "nf",
155
- "ng",
156
- "ni",
157
- "nl",
158
- "no",
159
- "np",
160
- "nr",
161
- "nu",
162
- "nz",
163
- "om",
164
- "pa",
165
- "pe",
166
- "pf",
167
- "pg",
168
- "ph",
169
- "pk",
170
- "pl",
171
- "pm",
172
- "pn",
173
- "pr",
174
- "ps",
175
- "pt",
176
- "pw",
177
- "py",
178
- "qa",
179
- "re",
180
- "ro",
181
- "ru",
182
- "rw",
183
- "sa",
184
- "sb",
185
- "sc",
186
- "sd",
187
- "se",
188
- "sg",
189
- "sh",
190
- "si",
191
- "sj",
192
- "sk",
193
- "sl",
194
- "sm",
195
- "sn",
196
- "so",
197
- "sr",
198
- "ss",
199
- "st",
200
- "sv",
201
- "sy",
202
- "sz",
203
- "tc",
204
- "td",
205
- "tf",
206
- "tg",
207
- "th",
208
- "tj",
209
- "tk",
210
- "tl",
211
- "tm",
212
- "tn",
213
- "to",
214
- "tr",
215
- "tt",
216
- "tv",
217
- "tz",
218
- "ua",
219
- "ug",
220
- "us",
221
- "uy",
222
- "uz",
223
- "va",
224
- "vc",
225
- "ve",
226
- "vg",
227
- "vi",
228
- "vn",
229
- "vu",
230
- "wf",
231
- "ws",
232
- "ye",
233
- "yt",
234
- "za",
235
- "zm",
236
- "zw"
237
- ]