Selama bertahun-tahun saya perlahan mengembangkan ekspresi reguler yang memvalidasi alamat email PALING dengan benar, dengan asumsi mereka tidak menggunakan alamat IP sebagai bagian server.
Saya menggunakannya di beberapa program PHP, dan itu berfungsi sebagian besar waktu. Namun, dari waktu ke waktu saya dihubungi oleh seseorang yang mengalami masalah dengan situs yang menggunakannya, dan saya akhirnya harus melakukan beberapa penyesuaian (baru-baru ini saya menyadari bahwa saya tidak mengizinkan TLD 4-karakter).
Apa ekspresi reguler terbaik yang Anda miliki atau lihat untuk memvalidasi email?
Saya telah melihat beberapa solusi yang menggunakan fungsi yang menggunakan beberapa ekspresi yang lebih pendek, tetapi saya lebih suka memiliki satu ekspresi kompleks panjang dalam fungsi sederhana daripada beberapa ekspresi pendek dalam fungsi yang lebih kompleks.
Jawaban:
The sepenuhnya RFC 822 regex compliant tidak efisien dan tidak jelas karena panjangnya. Untungnya, RFC 822 digantikan dua kali dan spesifikasi saat ini untuk alamat email adalah RFC 5322 . RFC 5322 mengarah ke regex yang dapat dipahami jika dipelajari selama beberapa menit dan cukup efisien untuk penggunaan aktual.
Satu regex compliant RFC 5322 dapat ditemukan di bagian atas halaman di http://emailregex.com/ tetapi menggunakan pola alamat IP yang mengambang di internet dengan bug yang memungkinkan
00
untuk setiap nilai desimal byte yang tidak ditandatangani dalam suatu alamat dot-delimited, yang ilegal. Sisanya tampaknya konsisten dengan tata bahasa RFC 5322 dan melewati beberapa tes menggunakangrep -Po
, termasuk nama domain kasus, alamat IP, yang buruk, dan nama akun dengan dan tanpa tanda kutip.Mengoreksi
00
bug dalam pola IP, kami memperoleh regex yang berfungsi dan cukup cepat. (Gosok versi yang diberikan, bukan penurunan harga, untuk kode aktual.)atau:
Berikut ini adalah diagram dari mesin negara yang terbatas untuk regexp di atas yang lebih jelas dari regexp sendiri
Pola yang lebih canggih dalam Perl dan PCRE (pustaka regex yang digunakan misalnya dalam PHP) dapat dengan benar mengurai RFC 5322 tanpa hambatan . Python dan C # dapat melakukannya juga, tetapi mereka menggunakan sintaks yang berbeda dari dua yang pertama. Namun, jika Anda terpaksa menggunakan salah satu dari banyak bahasa pencocokan pola yang kurang kuat, maka yang terbaik adalah menggunakan parser nyata.
Penting juga untuk dipahami bahwa memvalidasinya per RFC sama sekali tidak memberi tahu Anda apakah alamat itu benar-benar ada di domain yang disediakan, atau apakah orang yang memasukkan alamat itu adalah pemiliknya yang sebenarnya. Orang-orang mendaftar orang lain ke milis dengan cara ini sepanjang waktu. Memperbaiki yang memerlukan jenis validasi yang lebih menarik yang melibatkan pengiriman pesan yang menyertakan alamat konfirmasi yang dimaksudkan untuk dimasukkan pada halaman web yang sama dengan alamat.
Token konfirmasi adalah satu-satunya cara untuk mengetahui Anda mendapatkan alamat orang yang memasukkannya. Inilah sebabnya sebagian besar milis sekarang menggunakan mekanisme itu untuk mengonfirmasi pendaftaran. Lagipula, siapa pun dapat meletakkannya
[email protected]
, dan itu bahkan akan diurai sebagai legal, tetapi tidak mungkin menjadi orang di ujung lainnya.Untuk PHP, Anda sebaiknya tidak menggunakan pola yang diberikan dalam Validasi Alamat E-Mail dengan PHP, Cara yang Benar dari mana saya mengutip:
Itu tidak lebih baik dari semua pola non-RFC lainnya. Bahkan tidak cukup cerdas untuk menangani bahkan RFC 822 , apalagi RFC 5322. Yang satu ini , bagaimanapun, adalah.
Jika Anda ingin menjadi mewah dan gagah, menerapkan mesin negara lengkap . Ekspresi reguler hanya dapat bertindak sebagai filter yang belum sempurna. Masalah dengan ekspresi reguler adalah bahwa memberi tahu seseorang bahwa alamat email yang benar-benar valid tidak valid (false positive) karena ekspresi reguler Anda tidak dapat menanganinya itu tidak sopan dan tidak sopan dari sudut pandang pengguna. Mesin negara untuk tujuan tersebut dapat memvalidasi dan bahkan memperbaiki alamat email yang dinyatakan tidak valid karena membongkar alamat email sesuai dengan masing-masing RFC. Ini memungkinkan untuk pengalaman yang berpotensi lebih menyenangkan, seperti
Lihat juga Memvalidasi Alamat Email , termasuk komentar. Atau Membandingkan Alamat E-mail yang Memvalidasi Ekspresi Reguler .
Demo Debuggex
sumber
Anda tidak boleh menggunakan ekspresi reguler untuk memvalidasi alamat email.
Sebagai gantinya, gunakan kelas MailAddress , seperti ini:
The
MailAddress
kelas menggunakan parser BNF untuk memvalidasi alamat sesuai penuh dengan RFC822.Jika Anda berencana untuk menggunakan
MailAddress
untuk memvalidasi alamat email, ketahuilah bahwa pendekatan ini juga menerima bagian nama tampilan dari alamat email, dan itu mungkin tidak persis seperti apa yang ingin Anda capai. Misalnya, ia menerima string ini sebagai alamat email yang valid:Dalam beberapa kasus ini, hanya bagian terakhir dari string yang diuraikan sebagai alamat; sisanya sebelum itu adalah nama tampilan. Untuk mendapatkan alamat email biasa tanpa nama tampilan, Anda dapat memeriksa alamat yang dinormalisasi terhadap string asli Anda.
Selain itu, alamat yang memiliki titik di akhir, seperti
user@company.
juga diterima oleh MailAddress.Jika Anda benar-benar ingin menggunakan regex, ini dia :
sumber
[email protected]
. Anda tidak boleh mengandalkan validasi email untuk mencegah XSS.Pertanyaan ini banyak ditanyakan, tetapi saya pikir Anda harus mundur dan bertanya pada diri sendiri mengapa Anda ingin memvalidasi alamat email secara sintaksis? Apa manfaatnya sebenarnya?
Jika Anda ingin memvalidasi bahwa email itu benar, Anda tidak punya pilihan selain mengirim email konfirmasi dan meminta pengguna membalasnya. Dalam banyak kasus Anda tetap harus mengirim surat konfirmasi untuk alasan keamanan atau karena alasan etis (jadi Anda tidak bisa misalnya mendaftar seseorang ke layanan yang bertentangan dengan keinginan mereka).
sumber
me@hotmail
, mereka jelas tidak akan mendapatkan email konfirmasi Anda, lalu di mana mereka? Mereka tidak ada di situs Anda lagi dan mereka bertanya-tanya mengapa mereka tidak dapat mendaftar. Sebenarnya tidak, mereka tidak - mereka benar-benar lupa tentang Anda. Namun, jika Anda bisa melakukan pemeriksaan kewarasan dasar dengan regex saat mereka masih bersama Anda, maka mereka dapat langsung menangkap kesalahan itu dan Anda memiliki pengguna yang bahagia.[email protected]
alamat itu menunjukkan komandan tertinggi netbusy. :)Itu semua tergantung pada seberapa akurat yang Anda inginkan. Untuk tujuan saya, di mana saya hanya mencoba untuk mencegah hal-hal seperti
bob @ aol.com
(spasi di email) atausteve
(tidak ada domain sama sekali) ataumary@aolcom
(tidak ada periode sebelum .com), saya menggunakanTentu, ini akan cocok dengan hal-hal yang bukan alamat email yang valid, tetapi masalah mendapatkan kesalahan sederhana yang umum.
Ada sejumlah perubahan yang dapat dilakukan pada regex itu (dan beberapa ada di komentar untuk jawaban ini), tetapi sederhana, dan mudah dimengerti, dan merupakan upaya pertama yang bagus.
sumber
.
termasuk dalam\S
.mary@aolcom
daripada saya benar-benar sampah YMMV@
tanda - tanda:/^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/
jsfiddle.net/b9chris/mXB96Itu tergantung pada apa yang Anda maksud dengan yang terbaik: Jika Anda berbicara tentang menangkap setiap alamat email yang valid, gunakan yang berikut ini:
( http://www.ex-parrot.com/~pdw/Mail-RFC822-Address.html ) Jika Anda mencari sesuatu yang lebih sederhana tetapi itu akan menangkap sebagian besar alamat email yang valid coba sesuatu seperti:
EDIT: Dari tautan:
sumber
email address
yang salah melewati yang kedua, tetapi tertangkap oleh regex yang lebih lama?[DIPERBARUI] Saya telah mengumpulkan semua yang saya ketahui tentang validasi alamat email di sini: http://isemail.info , yang sekarang tidak hanya memvalidasi tetapi juga mendiagnosis masalah dengan alamat email. Saya setuju dengan banyak komentar di sini bahwa validasi hanya bagian dari jawabannya; lihat esai saya di http://isemail.info/about .
is_email () tetap, sejauh yang saya tahu, satu-satunya validator yang akan memberi tahu Anda secara pasti apakah string yang diberikan adalah alamat email yang valid atau tidak. Saya sudah mengunggah versi baru di http://isemail.info/
Saya mengumpulkan test case dari Cal Henderson, Dave Child, Phil Haack, Doug Lovell, RFC5322 dan RFC 3696. 275 alamat tes semuanya. Saya menjalankan semua tes ini terhadap semua validator gratis yang dapat saya temukan.
Saya akan mencoba menjaga halaman ini tetap mutakhir karena orang-orang meningkatkan validator mereka. Terima kasih kepada Cal, Michael, Dave, Paul dan Phil atas bantuan dan kerja sama mereka dalam menyusun tes-tes ini dan kritik yang membangun terhadap validator saya sendiri .
Orang-orang harus menyadari errata terhadap RFC 3696 pada khususnya. Tiga dari contoh kanonik sebenarnya adalah alamat yang tidak valid. Dan panjang maksimal alamat adalah 254 atau 256 karakter, bukan 320.
sumber
[email protected]
karena kode ini tentang validasi, bukan interpretasi. Jika Anda ingin menambahkan penerjemah punycode, maka saya senang menerima permintaan tarik di github.com/dominicsayers/isemailPer spesifikasi W3C HTML5 :
Konteks:
sumber
john.doe@localhost
benar. Yang pasti, dalam aplikasi dunia nyata (yaitu komunitas), saya ingin saran Anda untuk mengganti * dengan +"test...."@gmail.com
secara valid sesuai dengan RFC dan secara semantik setara dengan[email protected]
.Mudah di Perl 5.10 atau lebih baru:
sumber
addrspec
bagian yang benar-benar relevan dengan pertanyaan. Menerima lebih dari itu dan meneruskannya meskipun beberapa bagian lain dari sistem yang tidak siap menerima alamat RFC5822 lengkap seperti menembak adalah kaki Anda sendiri.saya menggunakan
Yang digunakan di ASP.NET oleh RegularExpressionValidator.
sumber
[email protected]
ditolak.^\\w+([-+.']\\w+)*@\\w+([-.]\\w+)*\\.\\w{2,}([-.]\\w+)*$
[email protected]
yang sebenarnya valid (pelanggan kami memiliki alamat yang sama) `Tidak tahu yang terbaik, tapi yang ini paling tidak benar, selama alamatnya dihapus dan diganti dengan spasi putih.
Serius. Anda harus menggunakan perpustakaan yang sudah ditulis untuk memvalidasi email. Cara terbaik adalah mengirim email verifikasi ke alamat itu.
sumber
Alamat email yang ingin saya validasi akan digunakan oleh aplikasi web ASP.NET menggunakan namespace System.Net.Mail untuk mengirim email ke daftar orang. Jadi, daripada menggunakan beberapa ekspresi reguler yang sangat kompleks, saya hanya mencoba membuat instance MailAddress dari alamat. Konstruktor MailAddress akan mengeluarkan pengecualian jika alamat tidak dibentuk dengan benar. Dengan cara ini, saya tahu saya setidaknya bisa mengeluarkan email dari pintu. Tentu saja ini adalah validasi sisi server tetapi setidaknya Anda memerlukannya.
sumber
args.Value
alih-alih merujuk pada bidang sepertitxtEmail.Text
hard-coded. Yang terakhir akan mengikat validator Anda ke instance kontrol tunggal, yang mungkin OK, selama Anda memiliki bidang email tunggal, tetapi tidak disarankan sebaliknya.Jawaban cepat
Gunakan regex berikut untuk validasi input:
([-!#-'*+/-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])?)+
Alamat yang cocok dengan regex ini:
Kendala kedua adalah pembatasan pada RFC 5321/5322.
Jawaban yang rumit
Menggunakan ekspresi reguler yang mengenali alamat email dapat berguna dalam berbagai situasi: misalnya untuk memindai alamat email dalam dokumen, untuk memvalidasi input pengguna, atau sebagai batasan integritas pada repositori data.
Namun perlu dicatat bahwa jika Anda ingin mengetahui apakah alamat tersebut benar-benar merujuk ke kotak surat yang ada, tidak ada pengganti untuk mengirim pesan ke alamat tersebut. Jika Anda hanya ingin memeriksa apakah suatu alamat secara tata bahasa benar maka Anda dapat menggunakan ekspresi reguler, tetapi perhatikan bahwa itu
""@[]
adalah alamat email yang benar secara tata bahasa yang tentu saja tidak merujuk ke kotak surat yang ada.Sintaks alamat email telah didefinisikan dalam berbagai RFC , terutama RFC 822 dan RFC 5322 . RFC 822 harus dilihat sebagai standar "asli" dan RFC 5322 sebagai standar terbaru. Sintaks yang didefinisikan dalam RFC 822 adalah standar yang paling lunak dan selanjutnya telah membatasi sintaks lebih lanjut dan lebih jauh, di mana sistem atau layanan yang lebih baru harus mengenali sintaks yang usang, tetapi tidak pernah memproduksinya.
Dalam jawaban ini saya akan mengambil "alamat email" untuk berarti
addr-spec
sebagaimana didefinisikan dalam RFC (yaitu[email protected]
, tetapi tidak"John Doe"<[email protected]>
, tidak jugasome-group:[email protected],[email protected];
).Ada satu masalah dengan menerjemahkan sintaks RFC ke dalam regex: sintaksinya tidak teratur! Ini karena mereka memungkinkan untuk komentar opsional di alamat email yang dapat disarangkan tanpa batas, sementara bersarang tanpa batas tidak dapat dijelaskan dengan ekspresi reguler. Untuk memindai atau memvalidasi alamat yang berisi komentar, Anda memerlukan parser atau ekspresi yang lebih kuat. (Perhatikan bahwa bahasa seperti Perl memiliki konstruksi untuk menggambarkan tata bahasa bebas konteks dengan cara seperti regex.) Dalam jawaban ini saya akan mengabaikan komentar dan hanya mempertimbangkan ekspresi reguler yang tepat.
RFC menentukan sintaksis untuk pesan email, bukan untuk alamat email. Alamat dapat muncul di berbagai bidang tajuk dan ini adalah tempat mereka ditentukan. Ketika mereka muncul di alamat bidang header mungkin berisi (antara token leksikal) spasi putih, komentar dan bahkan linebreak. Namun secara semantik ini tidak memiliki signifikansi. Dengan menghapus spasi putih ini, dll dari alamat, Anda mendapatkan representasi kanonik yang secara semantik setara . Dengan demikian, representasi kanonik
first. last (comment) @ [3.5.7.9]
adalahfirst.last@[3.5.7.9]
.Sintaks yang berbeda harus digunakan untuk tujuan yang berbeda. Jika Anda ingin memindai alamat email dalam dokumen (mungkin sangat lama) mungkin ide yang baik untuk menggunakan sintaksis seperti yang didefinisikan dalam RFC 822. Di sisi lain, jika Anda ingin memvalidasi input pengguna Anda mungkin ingin menggunakan sintaksis sebagaimana didefinisikan dalam RFC 5322, mungkin hanya menerima representasi kanonik. Anda harus memutuskan sintaksis mana yang berlaku untuk kasus spesifik Anda.
Saya menggunakan ekspresi reguler POSIX "extended" dalam jawaban ini, dengan asumsi rangkaian karakter yang kompatibel ASCII.
RFC 822
Saya tiba di ekspresi reguler berikut. Saya mengundang semua orang untuk mencoba dan memecahkannya. Jika Anda menemukan kesalahan positif atau negatif palsu, kirimkan dalam komentar dan saya akan mencoba untuk memperbaiki ekspresi sesegera mungkin.
([^][()<>@,;:\\". \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)*]))*
Saya percaya ini sepenuhnya sesuai dengan RFC 822 termasuk errata . Itu hanya mengenali alamat email dalam bentuk kanonik mereka. Untuk regex yang mengenali spasi (melipat) lihat derivasi di bawah ini.
Derivasi menunjukkan bagaimana saya sampai pada ekspresi. Saya mencantumkan semua aturan tata bahasa yang relevan dari RFC persis seperti yang muncul, diikuti oleh regex yang sesuai. Di mana erratum telah diterbitkan, saya memberikan ekspresi terpisah untuk aturan tata bahasa yang diperbaiki (ditandai "erratum") dan menggunakan versi yang diperbarui sebagai subekspresi dalam ekspresi reguler berikutnya.
Sebagaimana dinyatakan dalam paragraf 3.1.4. RFC 822 spasi putih linier opsional dapat dimasukkan di antara token leksikal. Jika berlaku, saya telah memperluas ekspresi untuk mengakomodasi aturan ini dan menandai hasilnya dengan "opt-lwsp".
RFC 5322
Saya tiba di ekspresi reguler berikut. Saya mengundang semua orang untuk mencoba dan memecahkannya. Jika Anda menemukan kesalahan positif atau negatif palsu, kirimkan dalam komentar dan saya akan mencoba untuk memperbaiki ekspresi sesegera mungkin.
([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|"([]!#-[^-~ \t]|(\\[\t -~]))+")@([-!#-'*+/-9=?A-Z^-~]+(\.[-!#-'*+/-9=?A-Z^-~]+)*|\[[\t -Z^-~]*])
Saya percaya ini sepenuhnya sesuai dengan RFC 5322 termasuk errata . Itu hanya mengenali alamat email dalam bentuk kanonik mereka. Untuk regex yang mengenali spasi (melipat) lihat derivasi di bawah ini.
Derivasi menunjukkan bagaimana saya sampai pada ekspresi. Saya mencantumkan semua aturan tata bahasa yang relevan dari RFC persis seperti yang muncul, diikuti oleh regex yang sesuai. Untuk aturan yang menyertakan spasi putih yang tidak relevan (melipat), saya memberikan regex terpisah bertanda "(dinormalisasi)" yang tidak menerima spasi putih ini.
Saya mengabaikan semua aturan "obs-" dari RFC. Ini berarti bahwa regex hanya cocok dengan alamat email yang sepenuhnya sesuai dengan RFC 5322. Jika Anda harus mencocokkan alamat "lama" (seperti tata bahasa yang lebih longgar termasuk aturan "obs-"), Anda dapat menggunakan salah satu dari regex RFC 822 dari paragraf sebelumnya.
Perhatikan bahwa beberapa sumber (terutama w3c ) mengklaim bahwa RFC 5322 terlalu ketat pada bagian lokal (yaitu bagian sebelum tanda-@). Ini karena "..", "a..b" dan "a." yang tidak valid dot-atom, sementara mereka dapat digunakan sebagai nama kotak surat. RFC, bagaimanapun, tidak memungkinkan untuk bagian lokal seperti ini, kecuali bahwa mereka telah dikutip. Jadi, alih-alih
[email protected]
Anda harus menulis"a..b"@example.net
, yang secara semantik setara.Pembatasan lebih lanjut
SMTP (sebagaimana didefinisikan dalam RFC 5321 ) lebih lanjut membatasi rangkaian alamat email yang valid (atau sebenarnya: nama kotak surat). Tampaknya masuk akal untuk menerapkan tata bahasa yang lebih ketat ini, sehingga alamat email yang cocok sebenarnya dapat digunakan untuk mengirim email.
RFC 5321 pada dasarnya menyisakan bagian "lokal" (yaitu bagian sebelum tanda @), tetapi lebih ketat pada bagian domain (yaitu bagian setelah tanda @). Ini memungkinkan hanya nama host yang menggantikan dot-atom dan address literal sebagai pengganti literal domain.
Tata bahasa yang disajikan dalam RFC 5321 terlalu lunak jika menyangkut nama host dan alamat IP. Saya mengambil kebebasan untuk "memperbaiki" aturan yang dimaksud, menggunakan konsep ini dan RFC 1034 sebagai pedoman. Inilah regex yang dihasilkan.
([-!#-'*+/-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^-~]+)])
Perhatikan bahwa tergantung pada kasus penggunaan, Anda mungkin tidak ingin mengizinkan "General-address-literal" di regex Anda. Juga perhatikan bahwa saya menggunakan lookahead negatif
(?!IPv6:)
di regex akhir untuk mencegah bagian "General-address-literal" untuk mencocokkan alamat IPv6 yang salah. Beberapa prosesor regex tidak mendukung tampilan negatif. Hapus substring|(?!IPv6:)[0-9A-Za-z-]*[0-9A-Za-z]:[!-Z^-~]+
dari regex jika Anda ingin mengeluarkan seluruh bagian "General-address-literal".Inilah derivasi:
Validasi input pengguna
Kasing penggunaan umum adalah validasi input pengguna, misalnya pada formulir html. Dalam hal ini, biasanya masuk akal untuk mencegah literal alamat dan membutuhkan setidaknya dua label dalam nama host. Mengambil regex RFC 5321 yang ditingkatkan dari bagian sebelumnya sebagai dasar, ekspresi yang dihasilkan adalah:
([-!#-'*+/-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])?)+
Saya tidak merekomendasikan untuk membatasi bagian lokal lebih lanjut, misalnya dengan menghalangi string yang dikutip, karena kita tidak tahu jenis nama kotak surat apa yang dibolehkan oleh beberapa host (suka
"a..b"@example.net
atau bahkan"a b"@example.net
).Saya juga tidak merekomendasikan memvalidasi secara eksplisit terhadap daftar domain tingkat atas literal atau bahkan memaksakan batasan panjang (ingat bagaimana ".museum" tidak valid
[a-z]{2,4}
), tetapi jika Anda harus:([-!#-'*+/-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|
dll ...)
Pastikan untuk tetap memperbarui regex Anda jika Anda memutuskan untuk turun ke jalur validasi domain tingkat atas eksplisit.
Pertimbangan lebih lanjut
Ketika hanya menerima nama host di bagian domain (setelah tanda @), regex di atas hanya menerima label dengan paling banyak 63 karakter, sebagaimana seharusnya. Namun, mereka tidak memaksakan fakta bahwa seluruh nama host harus paling panjang 253 karakter (termasuk titik-titik). Meskipun batasan ini secara tegas masih teratur, itu tidak layak untuk membuat regex yang menggabungkan aturan ini.
Pertimbangan lain, terutama ketika menggunakan regex untuk validasi input, adalah umpan balik kepada pengguna. Jika pengguna memasukkan alamat yang salah, alangkah baiknya memberikan sedikit lebih banyak umpan balik daripada "alamat yang salah secara sintaksis" yang sederhana. Dengan regex "vanilla" ini tidak mungkin.
Kedua pertimbangan ini dapat diatasi dengan menguraikan alamat. Batasan panjang ekstra pada nama host dalam beberapa kasus juga dapat diatasi dengan menggunakan regex tambahan yang memeriksanya, dan mencocokkan alamat dengan kedua ekspresi.
Tidak ada regex dalam jawaban ini yang dioptimalkan untuk kinerja. Jika kinerja merupakan masalah, Anda harus melihat apakah (dan bagaimana) regex pilihan Anda dapat dioptimalkan.
sumber
arbitrary-long-email-address-should-be-invalid-arbitrary-long-email-address-should-be-invalid.and-the-second-group-also-should-not-be-so-long-and-the-second-group-also-should-not-be-so-long@example.com
tidak boleh memvalidasi. Saya sarankan mengubah tanda "+" di grup pertama (nama sebelum titik opsional) dan di grup kedua (nama setelah titik-titik berikut) ke{1,64}
$emailRegex = '/^([-!#-\'*+\/-9=?A-Z^-~]{1,64}(\.[-!#-\'*+\/-9=?A-Z^-~]{1,64})*|"([]!#-[^-~ \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])?)+$/';
Ada banyak contoh hal ini di internet (dan saya pikir bahkan satu yang sepenuhnya memvalidasi RFC - tapi itu puluhan / ratusan baris lama jika ingatanku). Orang-orang cenderung terbujuk untuk membuktikan hal semacam ini. Mengapa tidak memeriksa saja apakah ada @ dan setidaknya satu. dan memenuhi beberapa panjang minimum sederhana. Sepele untuk memasukkan email palsu dan tetap cocok dengan regex yang valid. Saya kira positif palsu lebih baik daripada negatif palsu.
sumber
Saat memutuskan karakter mana yang diperbolehkan, harap ingat teman Anda yang telah ditulis ulang dan ditulis dengan tanda penghubung. Saya tidak memiliki kendali atas kenyataan bahwa perusahaan saya menghasilkan alamat email saya menggunakan nama saya dari sistem SDM. Itu termasuk tanda kutip di nama belakang saya. Saya tidak dapat memberi tahu Anda berapa kali saya diblokir untuk berinteraksi dengan situs web oleh fakta bahwa alamat email saya "tidak valid".
sumber
Regex ini dari Perl's Email :: Valid library. Saya percaya ini yang paling akurat, cocok dengan semua 822. Dan, ini didasarkan pada ekspresi reguler dalam buku O'Reilly:
sumber
Saat Anda menulis dalam PHP, saya akan menyarankan Anda untuk menggunakan validasi bawaan PHP untuk email.
Jika Anda menjalankan versi php lebih rendah dari 5.3.6 harap perhatikan masalah ini: https://bugs.php.net/bug.php?id=53091
Jika Anda ingin informasi lebih lanjut bagaimana validasi buid-in ini berfungsi, lihat di sini: Apakah filter_var PHP FILTER_VALIDATE_EMAIL sebenarnya berfungsi?
sumber
Cal Henderson (Flickr) menulis sebuah artikel yang disebut Parsing Email Adresses di PHP dan menunjukkan bagaimana melakukan parsing Alamat Email yang sesuai dengan RFC (2) 822. Anda juga bisa mendapatkan kode sumber dalam php , python dan ruby yang berlisensi cc .
sumber
a@b
itu valida@b
valid ... dalam hal inib
adalah domain tingkat atas.Saya tidak pernah repot mencipta dengan ekspresi reguler saya sendiri, karena kemungkinan orang lain telah membuat versi yang lebih baik. Saya selalu menggunakan regexlib untuk menemukan yang sesuai dengan keinginan saya.
sumber
Tidak ada satu yang benar-benar dapat digunakan.
Saya membahas beberapa masalah dalam jawaban saya untuk Apakah ada perpustakaan php untuk validasi alamat email? , dibahas juga dalam Regexp pengakuan alamat email yang sulit?
Singkatnya, jangan berharap satu regex yang dapat digunakan untuk melakukan pekerjaan yang tepat. Dan regex terbaik akan memvalidasi sintaks, bukan validitas email ([email protected] benar tetapi mungkin akan terpental ...).
sumber
Satu ungkapan reguler sederhana yang setidaknya tidak akan menolak alamat email yang valid adalah memeriksa sesuatu, diikuti oleh tanda @ dan kemudian sesuatu diikuti oleh tanda titik dan setidaknya 2 tanda sesuatu. Itu tidak akan menolak apa pun, tetapi setelah memeriksa spesifikasi, saya tidak dapat menemukan email apa pun yang valid dan ditolak.
email = ~
/.+@[^@]+\.[^@]{2,}$/
sumber
/^[^@]+@[^@]+\.[^@]{2}[^@]*$/
sebenarnya memeriksa 1 tanda @. Regex Anda akan membiarkan banyak masuk karena. * Pada akhirnya./^[^@]+@[^@]+\.[^@]{2,4}$/
memastikan bahwa itu diakhiri dengan 2 hingga 4 non @ karakter. Seperti yang ditunjukkan oleh @Josh, sekarang memungkinkan @ ekstra pada akhirnya. Tetapi Anda juga dapat mengubahnya juga menjadi:/^[^@]+@[^@]+\.[^a-z-A-Z]{2,4}$/
karena semua domain tingkat atas adalah karakter aZ. Anda dapat mengganti4
dengan5
atau lebih memungkinkan nama domain tingkat atas menjadi lebih lama di masa depan juga.Anda bisa menggunakan yang digunakan oleh plugin Validasi jQuery:
sumber
a-b'[email protected]
tetapi mampu menangkap variasi yang tidak pantas, sepertia-b'[email protected]
dana-b'[email protected]
Untuk evaluasi terlengkap dari ekspresi reguler terbaik untuk memvalidasi alamat email, lihat tautan ini; " Membandingkan Alamat E-mail yang Memvalidasi Ekspresi Reguler "
Berikut adalah ekspresi teratas saat ini untuk tujuan referensi:
sumber
Belum lagi bahwa nama domain non-Latin (Cina, Arab, Yunani, Ibrani, Sirilik, dan sebagainya) akan diizinkan dalam waktu dekat . Setiap orang harus mengubah regex email yang digunakan, karena karakter-karakter itu pasti tidak akan dicakup oleh
[a-z]/i
maupun\w
. Mereka semua akan gagal.Setelah semua, cara terbaik untuk memvalidasi alamat email masih benar-benar mengirim email ke alamat yang dimaksud untuk memvalidasi alamat. Jika alamat email adalah bagian dari otentikasi pengguna (daftar / login / dll), maka Anda dapat menggabungkannya dengan sempurna dengan sistem aktivasi pengguna. Yaitu mengirim email dengan tautan dengan kunci aktivasi unik ke alamat email yang ditentukan dan hanya mengizinkan login ketika pengguna telah mengaktifkan akun yang baru dibuat menggunakan tautan dalam email tersebut.
Jika tujuan regex hanya untuk dengan cepat memberi tahu pengguna di UI bahwa alamat email yang ditentukan tidak terlihat dalam format yang benar, yang terbaik adalah masih memeriksa apakah itu pada dasarnya cocok dengan regex berikut:
Sederhana seperti itu. Mengapa Anda peduli dengan karakter yang digunakan dalam nama dan domain? Adalah tanggung jawab klien untuk memasukkan alamat email yang valid, bukan server. Bahkan ketika klien memasukkan alamat email yang valid secara sintaksis seperti
[email protected]
, ini tidak menjamin bahwa itu adalah alamat email yang sah. Tidak ada satu regex yang bisa mengatasinya.sumber
spaces
setelah@.
eg.[email protected] com net
dianggap email yang valid dengan menggunakan regex di atas yang seharusnya tidak valid.Spesifikasi HTML5 menyarankan regex sederhana untuk memvalidasi alamat email:
Ini dengan sengaja tidak mematuhi RFC 5322 .
Total panjang juga dapat dibatasi hingga 254 karakter, per RFC 3696 errata 1690 .
sumber
invalid@emailaddress
. Saya akan mendorong hati-hati dan banyak pengujian sebelum Anda menggunakannya!Untuk demonstrasi yang jelas, monster berikut ini cukup bagus tetapi masih tidak mengenali semua alamat email yang valid secara sintaksis: ia mengenali komentar yang bersarang hingga kedalaman empat level.
Ini adalah pekerjaan untuk parser, tetapi bahkan jika suatu alamat secara sintaksis valid, itu masih mungkin tidak dapat dikirim. Kadang-kadang Anda harus menggunakan metode perbukitan "Hei, kalian semua, awasi kami!"
sumber
Menurut standar resmi RFC 2822 regex email yang valid adalah
jika Anda ingin menggunakannya di Jawa itu sangat sangat mudah
sumber
(?:[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
Inilah PHP yang saya gunakan. Saya telah memilih solusi ini dengan semangat "false positive lebih baik daripada false negative" sebagaimana dinyatakan oleh komentator lain di sini DAN sehubungan dengan menjaga waktu tanggapan Anda dan server memuat ... benar-benar tidak perlu membuang sumber daya server dengan ekspresi reguler saat ini akan menghilangkan kesalahan pengguna yang paling sederhana. Anda selalu dapat menindaklanjuti ini dengan mengirim email uji jika Anda mau.
sumber
RFC 5322 standar:
Mengizinkan dot-atom bagian lokal, bagian-string yang dikutip-lokal, bagian lokal yang usang (campuran dot-atom dan string-dikutip), domain nama domain, (IPv4, IPv6, dan alamat IPv6 yang dipetakan IPv4) domain domain literal, dan (bersarang) CFWS.
RFC 5321 standar:
Mengizinkan dot-atom lokal-bagian, string-lokal-dikutip, domain nama domain, dan (IPv4, IPv6, dan alamat IPv6 yang dipetakan IPv4) domain domain literal.
Dasar:
Mengizinkan dot-atom bagian lokal dan domain nama domain (membutuhkan setidaknya dua label nama domain dengan TLD terbatas pada 2-6 karakter alfabet).
sumber
/D
bendera, dan Anda telah mengutipnya dengan tanda kutip tunggal namun juga menggunakan garis miring untuk membatasi pola? Ini bukan Perl, dan itu tidak bisa PCRE. Apakah itu PHP? Saya percaya itu adalah tiga-satunya yang memungkinkan rekursi seperti(?1)
.Aneh bahwa Anda "tidak bisa" mengizinkan 4 karakter TLD. Anda melarang orang-orang dari .info dan .name , dan keterbatasan panjang berhenti .travel dan .museum , tapi ya, mereka kurang umum daripada 2 karakter TLDs dan 3 karakter TLDs.
Anda juga harus mengizinkan huruf besar. Sistem email akan menormalkan bagian lokal dan bagian domain.
Untuk regex bagian domain Anda, nama domain tidak dapat dimulai dengan '-' dan tidak dapat diakhiri dengan '-'. Dash hanya bisa tetap di antaranya.
Jika Anda menggunakan perpustakaan PEAR, periksa fungsi surat mereka (lupa nama / perpustakaan yang tepat). Anda dapat memvalidasi alamat email dengan memanggil satu fungsi, dan itu memvalidasi alamat email sesuai dengan definisi dalam RFC822.
sumber
sumber