Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/uri/mailto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class MailTo < Generic
HEADER_REGEXP = /\A(?<hfield>(?:%\h\h|[!$'-.0-;@-Z_a-z~])*=(?:%\h\h|[!$'-.0-;@-Z_a-z~])*)(?:&\g<hfield>)*\z/
# practical regexp for email address
# https://html.spec.whatwg.org/multipage/input.html#valid-e-mail-address
EMAIL_REGEXP = /\A(?!\.)[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+(?<!\.)@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
EMAIL_REGEXP = /\A(?!\.)(?!.*\.{2})[a-zA-Z0-9.!\#$%&'*+\/=?^_`{|}~-]+(?<!\.)@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\z/
Comment on lines 54 to +55
Copy link
Contributor

@osyoyu osyoyu Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As the comment above states, the original regex is mostly drawn from WHATWG HTML LS. This spec states that it intentionally violates RFC 5322 to provide a practical regex for validation.

This requirement is a willful violation of RFC 5322, which defines a syntax for email addresses that is simultaneously too strict (before the "@" character), too vague (after the "@" character), and too lax (allowing comments, whitespace characters, and quoted strings in manners unfamiliar to most users) to be of practical use here.

The allowing of .. is not the only deviation from RFC 5322. If a truly RFC 5322-compliant regexp is needed, I believe it should be organized under a different name, since too much departure from the original EMAIL_REGEXP must be introduced.

# :startdoc:

#
Expand Down
43 changes: 43 additions & 0 deletions test/uri/test_mailto.rb
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,49 @@ def test_check_to
assert_raise(URI::InvalidComponentError) do
u.to = 'n.@invalid.email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'n..t@invalid.email'
end

# Invalid host emails
assert_raise(URI::InvalidComponentError) do
u.to = 'a@.invalid.email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid.email.'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid..email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@-invalid.email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid-.email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid.-email'
end

assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid.email-'
end

u.to = 'a@'+'invalid'.ljust(63, 'd')+'.email'
assert_raise(URI::InvalidComponentError) do
u.to = 'a@'+'invalid'.ljust(64, 'd')+'.email'
end

u.to = 'a@invalid.'+'email'.rjust(63, 'e')
assert_raise(URI::InvalidComponentError) do
u.to = 'a@invalid.'+'email'.rjust(64, 'e')
end
end

def test_to_s
Expand Down
Loading