Advertisement
uriid1

E-mail validator | Lua 5.1+, LuaJit

Oct 1st, 2022 (edited)
1,100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.04 KB | None | 0 0
  1. --[[
  2.     ####--------------------------------####
  3.     #--# Author:   by uriid1            #--#
  4.     #--# License:  GNU GPLv3            #--#
  5.     #--# Telegram: @main_moderator      #--#
  6.     #--# E-mail:   [email protected]   #--#
  7.     ####--------------------------------####
  8. --]]
  9.  
  10. local function email_validator(str)
  11.     if type(str) ~= 'string' then
  12.         return false, 'E-mail is not a string'
  13.     end
  14.  
  15.     -- Capture
  16.     str = str:lower()
  17.     local re_local_part = '([a-z0-9%.!#%$%%&\'%*%+%-/=%?^_`{|}~%(%) "]+)'
  18.     local re_domain = '([a-z0-9%(%)%-%.:%[%]]+)'
  19.     local local_part, domain = str:match('^'..re_local_part..'@'..re_domain..'$')
  20.  
  21.     -- Check exists local-part and domain
  22.     if not local_part or not domain then
  23.         return false, 'Invalid local-part or domain name'
  24.     end
  25.  
  26.     -- Check length
  27.     if #local_part > 64 then
  28.         return false, 'Local-part over 64 symbol'
  29.     elseif #domain > 255 then
  30.         return false, 'Domain over 255 symbol'
  31.     end
  32.        
  33.     -- Check local-part in quotes
  34.     local text_in_quotes = local_part:match('^"(.+)"$')
  35.     if text_in_quotes then
  36.         if text_in_quotes:match('[^a-z0-9!#$%%&\'%*%+%-/=%?^_ `{|}~%.]') then
  37.            return false, 'Invalid characters in quotes local_part'
  38.         end
  39.     else
  40.         if local_part:find('"') then
  41.             return false, 'Invalid character " in local-part'
  42.         end
  43.     end
  44.  
  45.     -- Check comment
  46.     local comment_in_local_part = local_part:match('(%(.+%))')
  47.     if comment_in_local_part then
  48.         local some_text, count_char = comment_in_local_part:gsub('[()]', '')
  49.         if count_char > 2 then
  50.             return false, 'Multiple comment in local-part are not allowed'
  51.         end
  52.         local_part = local_part:gsub('%('..some_text..'%)', '')
  53.     end
  54.  
  55.     local comment_in_domain = domain:match('(%(.+%))')
  56.     if comment_in_domain then
  57.         local some_text, count_char = comment_in_domain:gsub('[()]', '')
  58.         if count_char > 2 then
  59.             return false, 'Multiple comment in domain are not allowed'
  60.         end
  61.         domain = domain:gsub('%('..some_text..'%)', '')
  62.     end
  63.  
  64.     -- Check [] characters in local-part
  65.     if local_part:match('%[.+%]') then
  66.         return false, 'Invalid local-part, characters []'
  67.     end
  68.  
  69.     -- Check correct local-part
  70.     if local_part:find("%.%.") or
  71.        local_part:find("%-%-") or
  72.        local_part:find("%+%+") then
  73.         return false, 'Too many periods in local-part'
  74.     end
  75.  
  76.     -- Dot pos check in local-part
  77.     if local_part:sub(1, 1) == '.' then
  78.         return false, 'Dot cannot be the first character'
  79.     elseif local_part:sub(-1) == '.' then
  80.         return false, 'Dot cannot be the last character'
  81.     end
  82.  
  83.     -- DNS domain check
  84.     local hostname = domain:match('^[%d%a%-%.]+$')
  85.     if hostname then
  86.         if domain:sub(0, 1) == '.' or
  87.            domain:sub(-1) == '.'   or
  88.            domain:find('%.%.')
  89.         then
  90.             return false, 'Invalid domain name'
  91.         end
  92.     end
  93.  
  94.     -- IpV4
  95.     local ipv4 = domain:match('^%[(.+)%]$')
  96.     if ipv4 then
  97.         local a, b, c, d = domain:match('(%d+)%.(%d+)%.(%d+)%.(%d+)')
  98.         if a and b and c and d then
  99.             if not ((tonumber(a) < 256) and
  100.                     (tonumber(b) < 256) and
  101.                     (tonumber(c) < 256) and
  102.                     (tonumber(d) < 256))
  103.             then
  104.                 return false, 'Invalid ipV4 domain'
  105.             end
  106.         end
  107.     end
  108.  
  109.     -- ipV6
  110.     local ipv6 = domain:match('^%[ipv6:(.-)%]$')
  111.     if ipv6 then
  112.         if not ipv6:find('^[a-f0-9]+'..(':[a-f0-9]+'):rep(7)..'$') then
  113.             return false, 'Invalid IPv6 domain'
  114.         end
  115.     end
  116.  
  117.     return true
  118. end
  119.  
  120.  
  121. -- Test
  122. print('[-- Valid --]')
  123. local valid = {
  124.     'simple@[127.128.0.255]';
  125.     'postmaster@[IPv6:2001:0db8:85a3:0000:0000:8a2e:0370:7334]';
  126.     'postmaster(coment)@domain.lol';
  127.     'postmaster@(comment)domain.lol';
  128. }
  129.  
  130. for i = 1, #valid do
  131.     local res, err = email_validator(valid[i])
  132.     if res then
  133.         print('Test:', i, res)
  134.     else
  135.         print('Test:', i, res, valid[i], err)
  136.     end
  137. end
  138.  
  139.  
  140. print('\n[-- Invalid --]')
  141. local invalid = {
  142.     'blablabla';
  143.     '   [email protected] ';
  144.     'Abc.example.com';
  145.     'A@b@[email protected]';
  146.     'a"b(c)d,e:f;g<h>i[j\\k][email protected]';
  147.     'just"not"[email protected]';
  148.     'this is"not\a[email protected]';
  149.     'this\\ still\\"not\\[email protected]';
  150.     '1234567890123456789012345678901234567890123456789012345678901234+x@example.com';
  151.     'i_like_underscore@but_its_not_allowed_in_this_part.example.com';
  152.     'QA[icon]CHOCOLATE[icon]@test.com';
  153.     '[]!@#$%^&@gmail.com';
  154. }
  155.  
  156. for i = 1, #invalid do
  157.     local res, err = email_validator(invalid[i])
  158.     if not res then
  159.         print('Test:', i, res)
  160.     else
  161.         print('Test:', i, res, invalid[i], err)
  162.     end
  163. end
Tags: lua
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement