शीघ्र जवाब
इनपुट सत्यापन के लिए निम्नलिखित रेगेक्स का उपयोग करें:
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+
इस regex द्वारा मिलान किए गए पते:
- एक स्थानीय हिस्सा (यानी @ -साइन से पहले वाला हिस्सा) जो RFC 5321/5322 के साथ सख्ती से अनुपालन करता है,
- एक डोमेन भाग (यानी @ -sign के बाद का हिस्सा) एक होस्ट नाम है जिसमें कम से कम दो लेबल होते हैं, जिनमें से प्रत्येक अधिक से अधिक 63 वर्णों का होता है।
दूसरा अवरोध RFC 5321/5322 पर प्रतिबंध है।
विस्तृत उत्तर
ईमेल पतों को पहचानने वाली एक नियमित अभिव्यक्ति का उपयोग करना विभिन्न स्थितियों में उपयोगी हो सकता है: उदाहरण के लिए किसी दस्तावेज़ में ईमेल पतों को स्कैन करने के लिए, उपयोगकर्ता इनपुट को मान्य करने के लिए, या डेटा रिपॉजिटरी में एक अखंडता बाधा के रूप में।
हालांकि यह ध्यान दिया जाना चाहिए कि यदि आप यह पता लगाना चाहते हैं कि क्या पता वास्तव में मौजूदा मेलबॉक्स को संदर्भित करता है, तो पते पर संदेश भेजने के लिए कोई विकल्प नहीं है। यदि आप केवल यह जांचना चाहते हैं कि क्या कोई पता व्याकरणिक रूप से सही है, तो आप एक नियमित अभिव्यक्ति का उपयोग कर सकते हैं, लेकिन ध्यान दें कि ""@[]
एक व्याकरणिक रूप से सही ईमेल पता है जो निश्चित रूप से मौजूदा मेलबॉक्स का संदर्भ नहीं देता है।
ईमेल पतों के वाक्य-विन्यास को विभिन्न RFC में परिभाषित किया गया है , विशेष रूप से RFC 822 और RFC 5322 । RFC 822 को "मूल" मानक और RFC 5322 को नवीनतम मानक के रूप में देखा जाना चाहिए। RFC 822 में परिभाषित सिंटैक्स सबसे उदार है और बाद के मानकों ने सिंटैक्स को आगे और आगे प्रतिबंधित कर दिया है, जहां नई प्रणालियों या सेवाओं को अप्रचलित सिंटैक्स को पहचानना चाहिए, लेकिन कभी भी इसका उत्पादन नहीं करना चाहिए।
इस उत्तर में मैं addr-spec
RFC में परिभाषित के रूप में "ईमेल पता" ले जाऊंगा (यानी jdoe@example.org
, लेकिन नहीं "John Doe"<jdoe@example.org>
, न ही some-group:jdoe@example.org,mrx@exampel.org;
)।
RFC सिंटैक्स को रेगेक्स में अनुवाद करने में एक समस्या है: सिंटैक्स नियमित नहीं होते हैं! ऐसा इसलिए है क्योंकि वे ईमेल पतों में वैकल्पिक टिप्पणियों के लिए अनुमति देते हैं जो असीम रूप से नेस्टेड हो सकते हैं, जबकि अनंत नेस्टिंग को एक नियमित अभिव्यक्ति द्वारा वर्णित नहीं किया जा सकता है। टिप्पणियों के लिए या मान्य पते स्कैन करने के लिए आपको एक पार्सर या अधिक शक्तिशाली अभिव्यक्ति की आवश्यकता होती है। (ध्यान दें कि पर्ल जैसी भाषाओं में संदर्भ मुक्त व्याकरणों का एक रेक्सक्स की तरह वर्णन करने के लिए निर्माण होता है।) इस उत्तर में मैं टिप्पणियों की अवहेलना करूंगा और केवल उचित नियमित भावों पर विचार करूंगा।
RFC ईमेल संदेशों के लिए वाक्यविन्यास को परिभाषित करता है, ईमेल पते के लिए नहीं। पते विभिन्न हेडर फ़ील्ड में दिखाई दे सकते हैं और यह वह जगह है जहाँ वे मुख्य रूप से परिभाषित होते हैं। जब वे हेडर फ़ील्ड में दिखाई देते हैं तो पते (लेक्सिकल टोकन के बीच) व्हाट्सएप, टिप्पणियां और यहां तक कि लाइनब्रेक हो सकते हैं। शब्दार्थ इसका कोई महत्व नहीं है। इस व्हाट्सएप इत्यादि को एक पते से हटाकर, आप एक शब्दार्थ रूप से समकक्ष विहित प्रतिनिधित्व प्राप्त करते हैं । इस प्रकार, विहित प्रतिनिधित्व first. last (comment) @ [3.5.7.9]
है first.last@[3.5.7.9]
।
विभिन्न उद्देश्यों के लिए अलग-अलग वाक्यविन्यास का उपयोग किया जाना चाहिए। यदि आप (संभवतः बहुत पुराने) दस्तावेज़ में ईमेल पते के लिए स्कैन करना चाहते हैं, तो यह RFC 822 में परिभाषित सिंटैक्स का उपयोग करने के लिए एक अच्छा विचार हो सकता है। दूसरी ओर, यदि आप उपयोगकर्ता इनपुट को मान्य करना चाहते हैं तो आप इसका उपयोग करना चाहते हैं। RFC 5322 में परिभाषित सिंटैक्स, शायद केवल कैनोनिकल अभ्यावेदन स्वीकार कर रहा है। आपको तय करना चाहिए कि आपके विशिष्ट मामले में कौन सा वाक्यविन्यास लागू होता है।
मैं इस जवाब में ASCII संगत वर्ण सेट मानकर POSIX "विस्तारित" नियमित अभिव्यक्ति का उपयोग करता हूं।
आरएफसी 822
मैं निम्नलिखित नियमित अभिव्यक्ति पर पहुंचा। मैं सभी को कोशिश करने और इसे तोड़ने के लिए आमंत्रित करता हूं। यदि आपको कोई झूठी सकारात्मक या गलत नकारात्मक मिलती है, तो कृपया उन्हें टिप्पणी में पोस्ट करें और मैं जल्द से जल्द अभिव्यक्ति को ठीक करने की कोशिश करूंगा।
([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*
मेरा मानना है कि यह इरेटा सहित RFC 822 के साथ पूरी तरह से अनुकूल है । यह केवल ईमेल पते को उनके विहित रूप में पहचानता है। एक regex के लिए जो पहचानता है (तह) व्हाट्सएप नीचे दिए गए व्युत्पत्ति को देखता है।
व्युत्पत्ति से पता चलता है कि मैं अभिव्यक्ति में कैसे आया। मैं RFC से सभी प्रासंगिक व्याकरण नियमों को सूचीबद्ध करता हूं, जैसा कि वे दिखाई देते हैं, उसके बाद संबंधित रेगेक्स। जहां एक इरेटा प्रकाशित किया गया है, मैं सही व्याकरण नियम ("इरेटम" के रूप में चिह्नित) के लिए एक अलग अभिव्यक्ति देता हूं और बाद के नियमित अभिव्यक्तियों में अपडेट किए गए संस्करण को सब-डेप्रिसिएशन के रूप में उपयोग करता हूं।
जैसा कि पैरा 3.1.4 में कहा गया है। RFC 822 वैकल्पिक रैखिक सफेद स्थान को लेक्सिकल टोकन के बीच डाला जा सकता है। जहां लागू हो, मैंने इस नियम को समायोजित करने के लिए भावों का विस्तार किया है और "ऑप्ट-lwsp" के साथ परिणाम को चिह्नित किया है।
CHAR = <any ASCII character>
=~ .
CTL = <any ASCII control character and DEL>
=~ [\x00-\x1F\x7F]
CR = <ASCII CR, carriage return>
=~ \r
LF = <ASCII LF, linefeed>
=~ \n
SPACE = <ASCII SP, space>
=~
HTAB = <ASCII HT, horizontal-tab>
=~ \t
<"> = <ASCII quote mark>
=~ "
CRLF = CR LF
=~ \r\n
LWSP-char = SPACE / HTAB
=~ [ \t]
linear-white-space = 1*([CRLF] LWSP-char)
=~ ((\r\n)?[ \t])+
specials = "(" / ")" / "<" / ">" / "@" / "," / ";" / ":" / "\" / <"> / "." / "[" / "]"
=~ [][()<>@,;:\\".]
quoted-pair = "\" CHAR
=~ \\.
qtext = <any CHAR excepting <">, "\" & CR, and including linear-white-space>
=~ [^"\\\r]|((\r\n)?[ \t])+
dtext = <any CHAR excluding "[", "]", "\" & CR, & including linear-white-space>
=~ [^][\\\r]|((\r\n)?[ \t])+
quoted-string = <"> *(qtext|quoted-pair) <">
=~ "([^"\\\r]|((\r\n)?[ \t])|\\.)*"
(erratum) =~ "(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"
domain-literal = "[" *(dtext|quoted-pair) "]"
=~ \[([^][\\\r]|((\r\n)?[ \t])|\\.)*]
(erratum) =~ \[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]
atom = 1*<any CHAR except specials, SPACE and CTLs>
=~ [^][()<>@,;:\\". \x00-\x1F\x7F]+
word = atom / quoted-string
=~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"
domain-ref = atom
sub-domain = domain-ref / domain-literal
=~ [^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]
local-part = word *("." word)
=~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*
(opt-lwsp) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*
domain = sub-domain *("." sub-domain)
=~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
addr-spec = local-part "@" domain
=~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(opt-lwsp) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*(\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*")((\r\n)?[ \t])*)*@((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*])(((\r\n)?[ \t])*\.((\r\n)?[ \t])*([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]|(\r\n)?[ \t]))*(\\\r)*]))*
(canonical) =~ ([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*")(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|"(\n|(\\\r)*([^"\\\r\n]|\\[^\r]))*(\\\r)*"))*@([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*])(\.([^][()<>@,;:\\". \x00-\x1F\x7F]+|\[(\n|(\\\r)*([^][\\\r\n]|\\[^\r]))*(\\\r)*]))*
RFC 5322
मैं निम्नलिखित नियमित अभिव्यक्ति पर पहुंचा। मैं सभी को कोशिश करने और इसे तोड़ने के लिए आमंत्रित करता हूं। यदि आपको कोई झूठी सकारात्मक या गलत नकारात्मक मिलती है, तो कृपया उन्हें टिप्पणी में पोस्ट करें और मैं जल्द से जल्द अभिव्यक्ति को ठीक करने की कोशिश करूंगा।
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])
मेरा मानना है कि यह इरेटा सहित RFC 5322 के साथ पूरी तरह से अनुकूल है । यह केवल ईमेल पते को उनके विहित रूप में पहचानता है। एक regex के लिए जो पहचानता है (तह) व्हाट्सएप नीचे दिए गए व्युत्पत्ति को देखता है।
व्युत्पत्ति से पता चलता है कि मैं अभिव्यक्ति में कैसे आया। मैं RFC से सभी प्रासंगिक व्याकरण नियमों को सूचीबद्ध करता हूं, जैसा कि वे दिखाई देते हैं, उसके बाद संबंधित रेगेक्स। ऐसे नियमों के लिए जिनमें शब्दशः अप्रासंगिक (फोल्डिंग) व्हाट्सएप शामिल है, मैं एक अलग रेग्क्स चिह्नित "(सामान्यीकृत)" देता हूं जो इस व्हाट्सएप को स्वीकार नहीं करता है।
मैंने RFC के सभी "अवलोकन" नियमों को अनदेखा किया। इसका मतलब यह है कि रेग्जेस केवल उन ईमेल पतों से मेल खाते हैं जो RFC 5322 के अनुरूप हैं। यदि आपको "पुराने" पतों ("जुनूनी" नियमों सहित शिथिल व्याकरण के रूप में) से मेल खाना है, तो आप पिछले पैराग्राफ से RFC 822 रेगेक्स में से एक का उपयोग कर सकते हैं।
VCHAR = %x21-7E
=~ [!-~]
ALPHA = %x41-5A / %x61-7A
=~ [A-Za-z]
DIGIT = %x30-39
=~ [0-9]
HTAB = %x09
=~ \t
CR = %x0D
=~ \r
LF = %x0A
=~ \n
SP = %x20
=~
DQUOTE = %x22
=~ "
CRLF = CR LF
=~ \r\n
WSP = SP / HTAB
=~ [\t ]
quoted-pair = "\" (VCHAR / WSP)
=~ \\[\t -~]
FWS = ([*WSP CRLF] 1*WSP)
=~ ([\t ]*\r\n)?[\t ]+
ctext = %d33-39 / %d42-91 / %d93-126
=~ []!-'*-[^-~]
("comment" is left out in the regex)
ccontent = ctext / quoted-pair / comment
=~ []!-'*-[^-~]|(\\[\t -~])
(not regular)
comment = "(" *([FWS] ccontent) [FWS] ")"
(is equivalent to FWS when leaving out comments)
CFWS = (1*([FWS] comment) [FWS]) / FWS
=~ ([\t ]*\r\n)?[\t ]+
atext = ALPHA / DIGIT / "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "/" / "=" / "?" / "^" / "_" / "`" / "{" / "|" / "}" / "~"
=~ [-!#-'*+/-9=?A-Z^-~]
dot-atom-text = 1*atext *("." 1*atext)
=~ [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*
dot-atom = [CFWS] dot-atom-text [CFWS]
=~ (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?
(normalized) =~ [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*
qtext = %d33 / %d35-91 / %d93-126
=~ []!#-[^-~]
qcontent = qtext / quoted-pair
=~ []!#-[^-~]|(\\[\t -~])
(erratum)
quoted-string = [CFWS] DQUOTE ((1*([FWS] qcontent) [FWS]) / FWS) DQUOTE [CFWS]
=~ (([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized) =~ "([]!#-[^-~ \t]|(\\[\t -~]))+"
dtext = %d33-90 / %d94-126
=~ [!-Z^-~]
domain-literal = [CFWS] "[" *([FWS] dtext) [FWS] "]" [CFWS]
=~ (([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized) =~ \[[\t -Z^-~]*]
local-part = dot-atom / quoted-string
=~ (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?
(normalized) =~ [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+"
domain = dot-atom / domain-literal
=~ (([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?
(normalized) =~ [-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*]
addr-spec = local-part "@" domain
=~ ((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?"(((([\t ]*\r\n)?[\t ]+)?([]!#-[^-~]|(\\[\t -~])))+(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?)"(([\t ]*\r\n)?[\t ]+)?)@((([\t ]*\r\n)?[\t ]+)?[-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*(([\t ]*\r\n)?[\t ]+)?|(([\t ]*\r\n)?[\t ]+)?\[((([\t ]*\r\n)?[\t ]+)?[!-Z^-~])*(([\t ]*\r\n)?[\t ]+)?](([\t ]*\r\n)?[\t ]+)?)
(normalized) =~ ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])
ध्यान दें कि कुछ स्रोत (विशेष रूप से w3c ) का दावा है कि RFC 5322 स्थानीय भाग (यानी @ -साइन से पहले वाला हिस्सा) पर बहुत सख्त है। ऐसा इसलिए है क्योंकि "..", "ए .. बी" और "ए।" हैं न वैध डॉट परमाणुओं, जबकि वे मेलबॉक्स नाम के रूप में इस्तेमाल किया जा सकता है। आरएफसी, तथापि, करता है इस तरह के स्थानीय भागों के लिए अनुमति देते हैं, सिवाय इसके कि वे उद्धृत किया जाना करने के लिए है। इसलिए इसके बजाय a..b@example.net
आपको लिखना चाहिए "a..b"@example.net
, जो शब्दार्थ के समकक्ष है।
आगे प्रतिबंध
SMTP (जैसा कि RFC 5321 में परिभाषित किया गया है ) आगे मान्य ईमेल पतों (या वास्तव में: मेलबॉक्स नाम) के सेट को प्रतिबंधित करता है। इस कड़े व्याकरण को थोपना उचित प्रतीत होता है, ताकि मेल किए गए ईमेल पते का उपयोग वास्तव में ईमेल भेजने के लिए किया जा सके।
RFC 5321 मूल रूप से "स्थानीय" भाग (यानी @ -sign से पहले वाला हिस्सा) को छोड़ देता है, लेकिन डोमेन भाग (यानी @ -sign के बाद वाला भाग) पर कठोर है। यह केवल डोमेन नाम के स्थान पर डॉट-परमाणुओं और एड्रेस शाब्दिकों के स्थान पर होस्ट नामों की अनुमति देता है।
RFC 5321 में प्रस्तुत व्याकरण तब बहुत हल्का होता है जब यह होस्ट नाम और IP पते दोनों के लिए आता है। मैंने इस ड्राफ्ट और RFC 1034 को दिशा-निर्देशों के रूप में उपयोग करते हुए, नियमों को "सही" करने की स्वतंत्रता ली । यहाँ परिणामी रेगेक्स है।
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])
ध्यान दें कि उपयोग के मामले के आधार पर आप अपने रेगेक्स में "सामान्य-पता-शाब्दिक" के लिए अनुमति नहीं देना चाहते हैं। यह भी ध्यान दें कि मैंने (?!IPv6:)
विकृत आईपीवी 6 पतों से मिलान करने के लिए "सामान्य-पता-शाब्दिक" भाग को रोकने के लिए अंतिम रेगेक्स में एक नकारात्मक रूपांतर का उपयोग किया था। कुछ रेगेक्स प्रोसेसर नकारात्मक लुकहेड का समर्थन नहीं करते हैं। |(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+
यदि आप पूरे "सामान्य-पता-शाब्दिक" भाग को बाहर निकालना चाहते हैं, तो रेगेक्स से सबस्ट्रिंग निकालें ।
यहाँ व्युत्पत्ति है:
Let-dig = ALPHA / DIGIT
=~ [0-9A-Za-z]
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
=~ [0-9A-Za-z-]*[0-9A-Za-z]
(regex is updated to make sure sub-domains are max. 63 charactes long - RFC 1034 section 3.5)
sub-domain = Let-dig [Ldh-str]
=~ [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?
Domain = sub-domain *("." sub-domain)
=~ [0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*
Snum = 1*3DIGIT
=~ [0-9]{1,3}
(suggested replacement for "Snum")
ip4-octet = DIGIT / %x31-39 DIGIT / "1" 2DIGIT / "2" %x30-34 DIGIT / "25" %x30-35
=~ 25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9]
IPv4-address-literal = Snum 3("." Snum)
=~ [0-9]{1,3}(\.[0-9]{1,3}){3}
(suggested replacement for "IPv4-address-literal")
ip4-address = ip4-octet 3("." ip4-octet)
=~ (25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}
(suggested replacement for "IPv6-hex")
ip6-h16 = "0" / ( (%x49-57 / %x65-70 /%x97-102) 0*3(%x48-57 / %x65-70 /%x97-102) )
=~ 0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}
(not from RFC)
ls32 = ip6-h16 ":" ip6-h16 / ip4-address
=~ (0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}
(suggested replacement of "IPv6-addr")
ip6-address = 6(ip6-h16 ":") ls32
/ "::" 5(ip6-h16 ":") ls32
/ [ ip6-h16 ] "::" 4(ip6-h16 ":") ls32
/ [ *1(ip6-h16 ":") ip6-h16 ] "::" 3(ip6-h16 ":") ls32
/ [ *2(ip6-h16 ":") ip6-h16 ] "::" 2(ip6-h16 ":") ls32
/ [ *3(ip6-h16 ":") ip6-h16 ] "::" ip6-h16 ":" ls32
/ [ *4(ip6-h16 ":") ip6-h16 ] "::" ls32
/ [ *5(ip6-h16 ":") ip6-h16 ] "::" ip6-h16
/ [ *6(ip6-h16 ":") ip6-h16 ] "::"
=~ (((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::
IPv6-address-literal = "IPv6:" ip6-address
=~ IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)
Standardized-tag = Ldh-str
=~ [0-9A-Za-z-]*[0-9A-Za-z]
dcontent = %d33-90 / %d94-126
=~ [!-Z^-~]
General-address-literal = Standardized-tag ":" 1*dcontent
=~ [0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+
address-literal = "[" ( IPv4-address-literal / IPv6-address-literal / General-address-literal ) "]"
=~ \[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)]
Mailbox = Local-part "@" ( Domain / address-literal )
=~ ([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)*|\[((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|IPv6:((((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){6}|::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){5}|[0-9A-Fa-f]{0,4}::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){4}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):)?(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){3}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,2}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){2}|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,3}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,4}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,5}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3})|(((0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}):){0,6}(0|[1-9A-Fa-f][0-9A-Fa-f]{0,3}))?::)|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+)])
उपयोगकर्ता इनपुट सत्यापन
एक सामान्य उपयोग का मामला उपयोगकर्ता इनपुट सत्यापन है, उदाहरण के लिए HTML फॉर्म। उस स्थिति में यह आमतौर पर पता-शाब्दिकों को छोड़ने और होस्टनाम में कम से कम दो लेबल लगाने के लिए उचित है। एक आधार के रूप में पिछले भाग से बेहतर RFC 5321 regex लेते हुए, परिणामी अभिव्यक्ति होगी:
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?(\.[0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?)+
मैं स्थानीय भाग को आगे प्रतिबंधित करने की सलाह नहीं देता, जैसे कि उद्धृत स्ट्रिंग को छोड़कर, क्योंकि हम नहीं जानते कि किस प्रकार के मेलबॉक्स कुछ मेजबान को अनुमति देते हैं (जैसे "a..b"@example.net
या भी "a b"@example.net
)।
मैं शाब्दिक शीर्ष-स्तरीय डोमेन की सूची या लंबाई-बाधाओं को लागू करने के खिलाफ स्पष्ट रूप से मान्य करने की अनुशंसा नहीं करता हूं (याद रखें कि कैसे ".Museum" अमान्य है [a-z]{2,4}
), लेकिन अगर आपको यह करना चाहिए:
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([0-9A-Za-z]([0-9A-Za-z-]{0,61}[0-9A-Za-z])?\.)*(net|org|com|info|
आदि...)
यदि आप स्पष्ट शीर्ष-स्तरीय डोमेन सत्यापन के पथ से नीचे जाने का निर्णय लेते हैं, तो अपने regex को अद्यतित रखना सुनिश्चित करें।
आगे के विचार
जब केवल डोमेन भाग (@ -sign के बाद) में होस्ट नामों को स्वीकार कर रहे हैं, तो ऊपर दिए गए संदर्भ केवल 63 अक्षरों के साथ केवल लेबल को स्वीकार करते हैं, जैसा कि उन्हें करना चाहिए। हालांकि, वे इस तथ्य को लागू नहीं करते हैं कि पूरे मेजबान का नाम अधिकतम 253 वर्ण (डॉट्स सहित) लंबा होना चाहिए। हालांकि यह बाधा कड़ाई से नियमित रूप से बोल रही है, लेकिन इस नियम को शामिल करने वाले रेगेक्स बनाने के लिए संभव नहीं है।
एक और विचार, विशेष रूप से इनपुट सत्यापन के लिए रेग्जेस का उपयोग करते समय, उपयोगकर्ता की प्रतिक्रिया है। यदि कोई उपयोगकर्ता किसी गलत पते पर प्रवेश करता है, तो एक साधारण "सिंटैक्टिकली गलत पते" की तुलना में थोड़ी अधिक प्रतिक्रिया देना अच्छा होगा। "वेनिला" के साथ यह संभव नहीं है।
पते पर विचार करके इन दोनों बातों पर ध्यान दिया जा सकता है। मेजबान नामों पर अतिरिक्त लंबाई की बाधा कुछ मामलों में एक अतिरिक्त रेगेक्स का उपयोग करके भी पता की जा सकती है जो इसे जांचता है, और दोनों अभिव्यक्तियों के खिलाफ पते का मिलान करता है।
इस उत्तर में कोई भी प्रतिक्षेप प्रदर्शन के लिए अनुकूलित नहीं है। यदि प्रदर्शन एक समस्या है, तो आपको यह देखना चाहिए कि क्या (और कैसे) आपकी पसंद का rexx अनुकूलित किया जा सकता है।