Skip to content

Instantly share code, notes, and snippets.

@james2doyle
Last active July 22, 2021 18:14
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save james2doyle/67846afd05335822c149 to your computer and use it in GitHub Desktop.
Save james2doyle/67846afd05335822c149 to your computer and use it in GitHub Desktop.
Lua validate email address
function validemail(str)
if str == nil or str:len() == 0 then return nil end
if (type(str) ~= 'string') then
error("Expected string")
return nil
end
local lastAt = str:find("[^%@]+$")
local localPart = str:sub(1, (lastAt - 2)) -- Returns the substring before '@' symbol
local domainPart = str:sub(lastAt, #str) -- Returns the substring after '@' symbol
-- we werent able to split the email properly
if localPart == nil then
return nil, "Local name is invalid"
end
if domainPart == nil or not domainPart:find("%.") then
return nil, "Domain is invalid"
end
if string.sub(domainPart, 1, 1) == "." then
return nil, "First character in domain cannot be a dot"
end
-- local part is maxed at 64 characters
if #localPart > 64 then
return nil, "Local name must be less than 64 characters"
end
-- domains are maxed at 253 characters
if #domainPart > 253 then
return nil, "Domain must be less than 253 characters"
end
-- somthing is wrong
if lastAt >= 65 then
return nil, "Invalid @ symbol usage"
end
-- quotes are only allowed at the beginning of a the local name
local quotes = localPart:find("[\"]")
if type(quotes) == 'number' and quotes > 1 then
return nil, "Invalid usage of quotes"
end
-- no @ symbols allowed outside quotes
if localPart:find("%@+") and quotes == nil then
return nil, "Invalid @ symbol usage in local part"
end
-- no dot found in domain name
if not domainPart:find("%.") then
return nil, "No TLD found in domain"
end
-- only 1 period in succession allowed
if domainPart:find("%.%.") then
return nil, "Too many periods in domain"
end
if localPart:find("%.%.") then
return nil, "Too many periods in local part"
end
-- just a general match
if not str:match('[%w]*[%p]*%@+[%w]*[%.]?[%w]*') then
return nil, "Email pattern test failed"
end
-- all our tests passed, so we are ok
return true
end
@shaiho
Copy link

shaiho commented Jan 29, 2017

there is a problem with this code. it returns true to "example@example" string.

i added this code to fix it:

-- no dot found in domain name
if not domainPart:find("%.") then
return nil, "Domain is invalid"
end

@pyk
Copy link

pyk commented Mar 9, 2017

Based on wikipedia invalid email addresses, this snippet is return true if the input john..doe@example.com.

Add the following rule to fix this:

-- only 1 period in succession allowed
if localPart:find("%.%.") then
    return false, "Too many periods in local part"
end

@james2doyle
Copy link
Author

@shaiho @pyk added your suggestions

@itech4ever
Copy link

Thanks a lot James (assume this is your name :-) ), adopted your code in my project and am now working perfectly, will let you know if I did any fix in the future.

Best,
Fuxin

@netSkinner
Copy link

Thanks for the script, but I found one small mistake.
If the symbol "@" is at the end of the address, the script breaks.

@Benzeliden
Copy link

@netSkinner nice catch

Adding check:

if (lastAt == nil) then lastAt = #str + 1 end

should fix it

@QuackingAtTheMoon
Copy link

I found another error. This string validates:
jack@.domain

Add this check:
if string.sub(domainPart, 1, 1) == "." then
return false, "first character in domainPart is a dot"
end

@itispey
Copy link

itispey commented Jul 22, 2021

The program will stop if string is empty ""
So, I added str:len checker:

if str:len() == 0 then return nil end

One more thing. This code will accept "@gmail.com" but it shouldn't accept it ?

@james2doyle
Copy link
Author

Added a bunch of checks from all the suggestions. Thanks everyone

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment