En iyi Java e-posta adresi doğrulama yöntemi nedir? [kapalı]


247

Java için iyi e-posta adresi doğrulama kitaplıkları nelerdir? Ortak doğrulayıcıya alternatif var mı?


15
Bunu burada bırakacağım: davidcelis.com/blog/2012/09/06/…
mpenkov


Kapsamlı olarak doğrulanmayan kütüphaneleri (veya normal ifadeleri) kullanmak istememelisiniz. Geçerli e-posta adresinin karmaşıklığı nedeniyle, hiçbir doğrulama ile kapsamlı doğrulama arasında bir orta yol yoktur. Apache Commons'ın uygulaması kapsamlı değildir . Sadece bir kütüphane olduğunu biliyorum ( email-rfc2822-validator ), ama yine de büyük regexes ile çalışıyor. Kapsamlı bir lexer gerçekten istediğiniz şeydir. EmailValidator4J işi yaptığını söylüyor, ancak bununla ilgili deneyimim yok.
Benny Bottema

1
@BennyBottema Soruyu yorum ile düzenlemek yerine, lütfen hâlâ sorularınız varsa bunun neden kapatıldığını tartışmak için bir Meta yayını yapın.
Machavity

Yanıtlar:


134

Apache Commons genellikle sağlam bir proje olarak bilinir. Yine de, bunun gerçek bir e-posta olduğundan ve sahibinin sitenizde kullanılmasını istediğinden emin olmak istiyorsanız adrese bir doğrulama e-postası göndermeniz gerektiğini unutmayın.

EDIT : Alan adında çok kısıtlayıcı olduğu ve yeni TLD'lerden geçerli e-postaları kabul etmemesine neden olan bir hata oluştu.

Bu hata 03 / Oca / 15 02:48 tarihinde commons-validator 1.4.1 sürümünde giderilmiştir.


1
Belirttiğiniz ekstra bitlere katılıyorum, ancak bunlar Commons Validation projesinin parçası mı?
duffymo

2
Hayır, Apache EmailValidatorsınıfı doğrulama için bir e-posta mesajı göndermez.
Matthew Flaschen

3
Kullanım durumunuz bir kullanıcının uzak e-posta adresini doğrulamaksa, bu çözümün önemli bir kusuru vardır (InternetAddress.validate () benzeri): EmailValidator, user @ [10.9.8.7] 'yi geçerli bir e-posta adresi olarak kabul eder. RFC, ancak kullanıcı kaydı / iletişim formu için olmayabilir.
zillion1

1
@zillion, Apache COmmons'da belgelenmiştir: "Bu uygulamanın bir e-posta adresindeki tüm olası hataları yakalaması garanti edilmez." "Gerçek bir e-posta olduğundan emin olmak" için ne yapmanız gerektiğini söyledim. Yerel IP'lere sahip adresler nadir ortamlarda geçerli olabilir.
Matthew Flaschen

5
Apache Commons EmailValidator'ın ciddi bir dezavantajı var: IDN'yi desteklemiyor.
Piohen

261

Kullanılması resmi java e-posta paketi en kolay:

public static boolean isValidEmailAddress(String email) {
   boolean result = true;
   try {
      InternetAddress emailAddr = new InternetAddress(email);
      emailAddr.validate();
   } catch (AddressException ex) {
      result = false;
   }
   return result;
}

59
InternetAddress.validate () yönteminin user @ [10.9.8.7] ve user @ localhost'u RFC'ye göre geçerli e-posta adresleri olarak gördüğünü unutmayın. Bununla birlikte, kullanım durumuna (web formu) bağlı olarak, bunları geçersiz olarak değerlendirmek isteyebilirsiniz.
zillion1

8
@ zillion1'in söylediği gibi geçerli değil, aynı zamanda bla @ bla gibi şeyler de geçerli sayılır. Gerçekten en iyi çözüm değil.
Diego Plentz

4
@NicholasTolleyCottrell Bu Java, burada istisnalar atıyoruz ve yakalıyoruz, gerçekten
anlamıyorum

17
InternetAddress kurucusunun kurcalandığından şüpheleniyorum. Veya sistemim üzerinde oynanmış. Veya RFC822 üzerinde oynanmış. Ya da şu an gerçekten biraz uyuyabiliyordum. Ama ben sadece bazı kod denedim ve InternetAddress yapıcısına geçerseniz, aşağıdaki beş dize geçerli e-posta adresleri olarak geçer ve "açıkça", onlar geçerli değildir. İşte başlıyoruz: ., .com, com., abcve 123. Ayrıca, öndeki veya sondaki boşluk eklemek de dizeleri geçersiz kılmaz. Hakim siz olun!
Martin Andersson

4
Ben koştuğumda peynir düzgün bir şekilde başarısız oluyor. cehennem javax.mail kütüphanesine ne bağlıyorsunuz ???
Aaron Davidson

91

Apache Commons validator diğer cevaplarda belirtildiği gibi kullanılabilir.

pom.xml:

<dependency>
    <groupId>commons-validator</groupId>
    <artifactId>commons-validator</artifactId>
    <version>1.4.1</version>
</dependency>

build.gradle:

compile 'commons-validator:commons-validator:1.4.1'

İçe aktarma:

import org.apache.commons.validator.routines.EmailValidator;

Kod:

String email = "myName@example.com";
boolean valid = EmailValidator.getInstance().isValid(email);

ve yerel adreslere izin vermek için

boolean allowLocal = true;
boolean valid = EmailValidator.getInstance(allowLocal).isValid(email);

2
Android Studio'da uygulamanız \ build.gradle bağımlılıklarına {}
Benjiko99

2
Aslında projemi oluşturmaya çalıştıktan sonra, apache commons Android ile çok iyi çalışmıyor, yüzlerce uyarı ve bazı hatalar, derlenmedi bile. Howtodoinjava.com/2014/11/11/java-regex-validate-email-address
Benjiko99

1
Benjiko99 ile aynı sorun. Bağımlılık ekledikten sonra, proje derlenmeyecek, java.exe sıfır olmayan çıkış kodu 2 ile bitirdi diyor
Amit Mittal

1
Android Studio'da da hatalar alıyordum. 1.4.1'den 1.5.1'e geçtim ve işe yarıyor!
Matt

1
Not: org.apache.commons.validator'daki EmailValidator kullanımdan kaldırıldığı için org.apache.commons.validator.routines öğesinde Email_validator kullanımdan kaldırılmıştır (1.6 ortak
doğrulayıcı

71

Geç cevap, ama bence basit ve değerli:

    public boolean isValidEmailAddress(String email) {
           String ePattern = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$";
           java.util.regex.Pattern p = java.util.regex.Pattern.compile(ePattern);
           java.util.regex.Matcher m = p.matcher(email);
           return m.matches();
    }

Test Durumları :

resim açıklamasını buraya girin

Üretim amacıyla Alan Adı doğrulamaları ağ üzerinden gerçekleştirilmelidir.


40
Bu, IDN'lerle birlikte RFC kurallarının çoğunu göz ardı eden oldukça vahşice basit bir doğrulayıcıdır. Herhangi bir üretim kalitesi uygulaması için bundan uzak dururum.
Aralık'ta mlaccetti

1
me@company.co.uk geçerli olmayacak ...
Alexander Burakevych

14
RFC'lerin kapsadığı şeyler için kendi normal ifade tabanlı doğrulayıcınızı döndürmeyin.
Josh Glover

6
arada
patlak

iyi ama tüm durumlar için değil.
Andrain

21

İstemciden alınan bir form doğrulaması veya sadece bir fasulye doğrulaması yapmaya çalışıyorsanız, bunu basit tutun. Sıkı bir e-posta doğrulaması yapmak ve bazı kişileri reddetmek yerine (örneğin, web hizmetinize kaydolmaya çalışırken) gevşek bir e-posta doğrulaması yapmak daha iyidir. E-postanın kullanıcı adı bölümünde neredeyse her şeye izin verilir ve her ay kelimenin tam anlamıyla çok sayıda yeni alan eklenir (ör. Şirket, .entreprise, .estate), kısıtlayıcı olmamak daha güvenlidir:

Pattern pattern = Pattern.compile("^.+@.+\\..+$");
Matcher matcher = pattern.matcher(email);

3
Bu gerçekten iyi bir nokta, herhangi bir makul uygulama yine de bu girişin hatta sömürülmesini önlemek için başka önlemler olmalıdır
18'de jmaculate

4
Sondaki noktadan kaçınmak için "^. + @. + (\\. [^ \\.] +) + $" Olarak değiştirmeye ne dersiniz?
Xingang Huang

7

Soruya geç, burada, ama: Bu adreste bir sınıfım var: http://lacinato.com/cm/software/emailrelated/emailaddress

Les Hazlewood'un sınıfına dayanıyor, ancak çok sayıda iyileştirme var ve birkaç hata düzeltiyor. Apache lisansı.

Java'daki en yetenekli e-posta ayrıştırıcı olduğuna inanıyorum ve henüz herhangi bir dilde daha yetenekli bir e-posta ayrıştırıcısı görmedim, ancak orada bir tane olabilir. Lexer tarzı bir ayrıştırıcı değil, ancak bazı karmaşık java regex kullanıyor ve bu nedenle olabildiğince verimli değil, ancak şirketim 10 milyardan fazla gerçek dünya adresini ayrıştırdı: kesinlikle yüksek performanslı olarak kullanılabilir durum. Belki yılda bir kez regex yığını taşmasına neden olan bir adrese (uygun şekilde) çarpacaktır, ancak bunlar yüzlerce veya binlerce karakter uzunluğunda çok sayıda tırnak ve parantez ve benzeri olan spam adresleridir.

RFC 2822 ve ilgili spesifikasyonlar e-posta adresleri açısından gerçekten oldukça izin vericidir, bu nedenle böyle bir sınıf çoğu kullanım için aşırıdır. Örneğin, spec, boşluklar ve her şeye göre aşağıdaki adreste geçerli bir adrestir:

"<bob \" (here) " < (hi there) "bob(the man)smith" (hi) @ (there) example.com (hello) > (again)

Hiçbir posta sunucusu buna izin vermez, ancak bu sınıf onu ayrıştırabilir (ve kullanılabilir bir forma yeniden yazabilir).

Mevcut Java e-posta ayrıştırıcı seçeneklerini yeterince dayanıklı bulduk (yani, bazı geçerli adresleri ayrıştıramadı), bu yüzden bu sınıfı oluşturduk.

Kod iyi belgelenmiştir ve belirli e-posta formlarına izin vermek veya izin vermemek için birçok kolay değiştirilebilir seçeneğe sahiptir. Ayrıca, posta kutusu listesi başlıklarını ayrıştırmak / doğrulamak, dönüş yolunu ayrıştırmak / doğrulamak için adresin belirli bölümlerine (sol taraf, sağ taraf, kişisel adlar, yorumlar vb.) Erişmek için birçok yöntem sağlar. (başlıklar arasında benzersizdir) vb.

Yazılan kodun javamail bağımlılığı vardır, ancak sağladığı küçük işlevselliği istemiyorsanız kaldırmak kolaydır.


1
Merhaba, açık kaynak topluluğu halka açmak için GitHub'a kopyaladım. Artık herkes kod hakkında yorum yapabilir, dokümante edebilir ve geliştirebilir. github.com/bbottema/email-rfc2822-validator . Les'ın eski sürümünü kullanıyordum, ancak regex dondurma hataları nedeniyle kaldırmak zorunda kaldım: leshazlewood.com/2006/11/06/emailaddress-java-class/…
Benny Bottema

7

Sadece neden @EmailHibernate Validator'ın ek kısıtlamalarından kimsenin gelmediğini merak ediyorum . Doğrulayıcının kendisi EmailValidator.


Apache müştereklerine bir alternatif olmasına rağmen, uygulaması çoğu normal ifade tabanlı kütüphaneler kadar basittir. Dokümanlardan: "Ancak, bu makalede açıklandığı gibi,% 100 uyumlu bir e-posta doğrulayıcı uygulamak zorunlu değildir". Bildiğim tek regex tabanlı kapsamlı validator email-rfc2822-validator ve aksi takdirde EmailValidator4J umut verici görünüyor.
Benny Bottema

5

Les Hazlewood, Java düzenli ifadeleri kullanarak çok kapsamlı bir RFC 2822 uyumlu e-posta doğrulama sınıfı yazmıştır. Http://www.leshazlewood.com/?p=23 adresinde bulabilirsiniz . Ancak, kapsamlılığı (veya Java RE uygulaması) verimsizliğe yol açar - uzun adresler için ayrıştırma süreleri hakkındaki yorumları okuyun.


1
Les Hazlewood mükemmel sınıf (ki bazı hatalar var) üzerine inşa. (Bu soruya verdiğim ayrı cevaba bakın.) Java regex yöntemini sürdürmeme rağmen, performansı kritik bir ortamda iyi kullanıyoruz. Yaptığınız tek şey adresleri ayrıştırmaksa, performans bir sorun olabilir, ancak çoğu kullanıcı için bunun ne yaptıklarının sadece başlangıcı olduğundan şüphelenirim. Sınıfa yönelik güncellemelerim, bir dizi uzun özyineleme sorununu da düzeltti.
lacinato

Bu eskimiş bir kütüphane ve iki kez, nihayet email-rfc2822-validator tarafından değiştirildi . Hala tüm modern ihtiyaçlara uysa da, yine de gizli performans hatalarına eğilimlidir (ve daha yeni RFC spesifikasyonlarının sınırlı değişikliklerini desteklemez).
Benny Bottema

3

Kodun bazılarını Zend_Validator_Email'de taşıdım:

@FacesValidator("emailValidator")
public class EmailAddressValidator implements Validator {

    private String localPart;
    private String hostName;
    private boolean domain = true;

    Locale locale;
    ResourceBundle bundle;

    private List<FacesMessage> messages = new ArrayList<FacesMessage>();

    private HostnameValidator hostnameValidator;

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        setOptions(component);
        String email    = (String) value;
        boolean result  = true;
        Pattern pattern = Pattern.compile("^(.+)@([^@]+[^.])$");
        Matcher matcher = pattern.matcher(email);

        locale = context.getViewRoot().getLocale();
        bundle = ResourceBundle.getBundle("com.myapp.resources.validationMessages", locale);

        boolean length = true;
        boolean local  = true;

        if (matcher.find()) {
            localPart   = matcher.group(1);
            hostName    = matcher.group(2);

            if (localPart.length() > 64 || hostName.length() > 255) {
                length          = false;
                addMessage("enterValidEmail", "email.AddressLengthExceeded");
            } 

            if (domain == true) {
                hostnameValidator = new HostnameValidator();
                hostnameValidator.validate(context, component, hostName);
            }

            local = validateLocalPart();

            if (local && length) {
                result = true;
            } else {
                result = false;
            }

        } else {
            result          = false;
            addMessage("enterValidEmail", "invalidEmailAddress");
        }

        if (result == false) {
            throw new ValidatorException(messages);
        }

    }

    private boolean validateLocalPart() {
        // First try to match the local part on the common dot-atom format
        boolean result = false;

        // Dot-atom characters are: 1*atext *("." 1*atext)
        // atext: ALPHA / DIGIT / and "!", "#", "$", "%", "&", "'", "*",
        //        "+", "-", "/", "=", "?", "^", "_", "`", "{", "|", "}", "~"
        String atext = "a-zA-Z0-9\\u0021\\u0023\\u0024\\u0025\\u0026\\u0027\\u002a"
                + "\\u002b\\u002d\\u002f\\u003d\\u003f\\u005e\\u005f\\u0060\\u007b"
                + "\\u007c\\u007d\\u007e";
        Pattern regex = Pattern.compile("^["+atext+"]+(\\u002e+["+atext+"]+)*$");
        Matcher matcher = regex.matcher(localPart);
        if (matcher.find()) {
            result = true;
        } else {
            // Try quoted string format

            // Quoted-string characters are: DQUOTE *([FWS] qtext/quoted-pair) [FWS] DQUOTE
            // qtext: Non white space controls, and the rest of the US-ASCII characters not
            //   including "\" or the quote character
            String noWsCtl = "\\u0001-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f";
            String qText = noWsCtl + "\\u0021\\u0023-\\u005b\\u005d-\\u007e";
            String ws = "\\u0020\\u0009";

            regex = Pattern.compile("^\\u0022(["+ws+qText+"])*["+ws+"]?\\u0022$");
            matcher = regex.matcher(localPart);
            if (matcher.find()) {
                result = true;
            } else {
                addMessage("enterValidEmail", "email.AddressDotAtom");
                addMessage("enterValidEmail", "email.AddressQuotedString");
                addMessage("enterValidEmail", "email.AddressInvalidLocalPart");
            }
        }

        return result;
    }

    private void addMessage(String detail, String summary) {
        String detailMsg = bundle.getString(detail);
        String summaryMsg = bundle.getString(summary);
        messages.add(new FacesMessage(FacesMessage.SEVERITY_ERROR, summaryMsg, detailMsg));
    }

    private void setOptions(UIComponent component) {
        Boolean domainOption = Boolean.valueOf((String) component.getAttributes().get("domain"));
        //domain = (domainOption == null) ? true : domainOption.booleanValue();
    }
}

Aşağıdaki gibi bir ana bilgisayar adı doğrulayıcısıyla:

@FacesValidator("hostNameValidator")
public class HostnameValidator implements Validator {

    private Locale locale;
    private ResourceBundle bundle;
    private List<FacesMessage> messages;
    private boolean checkTld = true;
    private boolean allowLocal = false;
    private boolean allowDNS = true;
    private String tld;
    private String[] validTlds = {"ac", "ad", "ae", "aero", "af", "ag", "ai",
        "al", "am", "an", "ao", "aq", "ar", "arpa", "as", "asia", "at", "au",
        "aw", "ax", "az", "ba", "bb", "bd", "be", "bf", "bg", "bh", "bi", "biz",
        "bj", "bm", "bn", "bo", "br", "bs", "bt", "bv", "bw", "by", "bz", "ca",
        "cat", "cc", "cd", "cf", "cg", "ch", "ci", "ck", "cl", "cm", "cn", "co",
        "com", "coop", "cr", "cu", "cv", "cx", "cy", "cz", "de", "dj", "dk",
        "dm", "do", "dz", "ec", "edu", "ee", "eg", "er", "es", "et", "eu", "fi",
        "fj", "fk", "fm", "fo", "fr", "ga", "gb", "gd", "ge", "gf", "gg", "gh",
        "gi", "gl", "gm", "gn", "gov", "gp", "gq", "gr", "gs", "gt", "gu", "gw",
        "gy", "hk", "hm", "hn", "hr", "ht", "hu", "id", "ie", "il", "im", "in",
        "info", "int", "io", "iq", "ir", "is", "it", "je", "jm", "jo", "jobs",
        "jp", "ke", "kg", "kh", "ki", "km", "kn", "kp", "kr", "kw", "ky", "kz",
        "la", "lb", "lc", "li", "lk", "lr", "ls", "lt", "lu", "lv", "ly", "ma",
        "mc", "md", "me", "mg", "mh", "mil", "mk", "ml", "mm", "mn", "mo",
        "mobi", "mp", "mq", "mr", "ms", "mt", "mu", "museum", "mv", "mw", "mx",
        "my", "mz", "na", "name", "nc", "ne", "net", "nf", "ng", "ni", "nl",
        "no", "np", "nr", "nu", "nz", "om", "org", "pa", "pe", "pf", "pg", "ph",
        "pk", "pl", "pm", "pn", "pr", "pro", "ps", "pt", "pw", "py", "qa", "re",
        "ro", "rs", "ru", "rw", "sa", "sb", "sc", "sd", "se", "sg", "sh", "si",
        "sj", "sk", "sl", "sm", "sn", "so", "sr", "st", "su", "sv", "sy", "sz",
        "tc", "td", "tel", "tf", "tg", "th", "tj", "tk", "tl", "tm", "tn", "to",
        "tp", "tr", "travel", "tt", "tv", "tw", "tz", "ua", "ug", "uk", "um",
        "us", "uy", "uz", "va", "vc", "ve", "vg", "vi", "vn", "vu", "wf", "ws",
        "ye", "yt", "yu", "za", "zm", "zw"};
    private Map<String, Map<Integer, Integer>> idnLength;

    private void init() {
        Map<Integer, Integer> biz = new HashMap<Integer, Integer>();
        biz.put(5, 17);
        biz.put(11, 15);
        biz.put(12, 20);

        Map<Integer, Integer> cn = new HashMap<Integer, Integer>();
        cn.put(1, 20);

        Map<Integer, Integer> com = new HashMap<Integer, Integer>();
        com.put(3, 17);
        com.put(5, 20);

        Map<Integer, Integer> hk = new HashMap<Integer, Integer>();
        hk.put(1, 15);

        Map<Integer, Integer> info = new HashMap<Integer, Integer>();
        info.put(4, 17);

        Map<Integer, Integer> kr = new HashMap<Integer, Integer>();
        kr.put(1, 17);

        Map<Integer, Integer> net = new HashMap<Integer, Integer>();
        net.put(3, 17);
        net.put(5, 20);

        Map<Integer, Integer> org = new HashMap<Integer, Integer>();
        org.put(6, 17);

        Map<Integer, Integer> tw = new HashMap<Integer, Integer>();
        tw.put(1, 20);

        Map<Integer, Integer> idn1 = new HashMap<Integer, Integer>();
        idn1.put(1, 20);

        Map<Integer, Integer> idn2 = new HashMap<Integer, Integer>();
        idn2.put(1, 20);

        Map<Integer, Integer> idn3 = new HashMap<Integer, Integer>();
        idn3.put(1, 20);

        Map<Integer, Integer> idn4 = new HashMap<Integer, Integer>();
        idn4.put(1, 20);

        idnLength = new HashMap<String, Map<Integer, Integer>>();

        idnLength.put("BIZ", biz);
        idnLength.put("CN", cn);
        idnLength.put("COM", com);
        idnLength.put("HK", hk);
        idnLength.put("INFO", info);
        idnLength.put("KR", kr);
        idnLength.put("NET", net);
        idnLength.put("ORG", org);
        idnLength.put("TW", tw);
        idnLength.put("ایران", idn1);
        idnLength.put("中国", idn2);
        idnLength.put("公司", idn3);
        idnLength.put("网络", idn4);

        messages = new ArrayList<FacesMessage>();
    }

    public HostnameValidator() {
        init();
    }

    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        String hostName = (String) value;

        locale = context.getViewRoot().getLocale();
        bundle = ResourceBundle.getBundle("com.myapp.resources.validationMessages", locale);

        Pattern ipPattern = Pattern.compile("^[0-9a-f:\\.]*$", Pattern.CASE_INSENSITIVE);
        Matcher ipMatcher = ipPattern.matcher(hostName);
        if (ipMatcher.find()) {
            addMessage("hostname.IpAddressNotAllowed");
            throw new ValidatorException(messages);
        }

        boolean result = false;

        // removes last dot (.) from hostname 
        hostName = hostName.replaceAll("(\\.)+$", "");
        String[] domainParts = hostName.split("\\.");

        boolean status = false;

        // Check input against DNS hostname schema
        if ((domainParts.length > 1) && (hostName.length() > 4) && (hostName.length() < 255)) {
            status = false;

            dowhile:
            do {
                // First check TLD
                int lastIndex = domainParts.length - 1;
                String domainEnding = domainParts[lastIndex];
                Pattern tldRegex = Pattern.compile("([^.]{2,10})", Pattern.CASE_INSENSITIVE);
                Matcher tldMatcher = tldRegex.matcher(domainEnding);
                if (tldMatcher.find() || domainEnding.equals("ایران")
                        || domainEnding.equals("中国")
                        || domainEnding.equals("公司")
                        || domainEnding.equals("网络")) {



                    // Hostname characters are: *(label dot)(label dot label); max 254 chars
                    // label: id-prefix [*ldh{61} id-prefix]; max 63 chars
                    // id-prefix: alpha / digit
                    // ldh: alpha / digit / dash

                    // Match TLD against known list
                    tld = (String) tldMatcher.group(1).toLowerCase().trim();
                    if (checkTld == true) {
                        boolean foundTld = false;
                        for (int i = 0; i < validTlds.length; i++) {
                            if (tld.equals(validTlds[i])) {
                                foundTld = true;
                            }
                        }

                        if (foundTld == false) {
                            status = false;
                            addMessage("hostname.UnknownTld");
                            break dowhile;
                        }
                    }

                    /**
                     * Match against IDN hostnames
                     * Note: Keep label regex short to avoid issues with long patterns when matching IDN hostnames
                     */
                    List<String> regexChars = getIdnRegexChars();

                    // Check each hostname part
                    int check = 0;
                    for (String domainPart : domainParts) {
                        // Decode Punycode domainnames to IDN
                        if (domainPart.indexOf("xn--") == 0) {
                            domainPart = decodePunycode(domainPart.substring(4));
                        }

                        // Check dash (-) does not start, end or appear in 3rd and 4th positions
                        if (domainPart.indexOf("-") == 0
                                || (domainPart.length() > 2 && domainPart.indexOf("-", 2) == 2 && domainPart.indexOf("-", 3) == 3)
                                || (domainPart.indexOf("-") == (domainPart.length() - 1))) {
                            status = false;
                            addMessage("hostname.DashCharacter");
                            break dowhile;
                        }

                        // Check each domain part
                        boolean checked = false;

                        for (int key = 0; key < regexChars.size(); key++) {
                            String regexChar = regexChars.get(key);
                            Pattern regex = Pattern.compile(regexChar);
                            Matcher regexMatcher = regex.matcher(domainPart);
                            status = regexMatcher.find();
                            if (status) {
                                int length = 63;

                                if (idnLength.containsKey(tld.toUpperCase())
                                        && idnLength.get(tld.toUpperCase()).containsKey(key)) {
                                    length = idnLength.get(tld.toUpperCase()).get(key);
                                }

                                int utf8Length;
                                try {
                                    utf8Length = domainPart.getBytes("UTF8").length;
                                    if (utf8Length > length) {
                                        addMessage("hostname.InvalidHostname");
                                    } else {
                                        checked = true;
                                        break;
                                    }
                                } catch (UnsupportedEncodingException ex) {
                                    Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex);
                                }


                            }
                        }


                        if (checked) {
                            ++check;
                        }
                    }

                    // If one of the labels doesn't match, the hostname is invalid
                    if (check != domainParts.length) {
                        status = false;
                        addMessage("hostname.InvalidHostnameSchema");

                    }
                } else {
                    // Hostname not long enough
                    status = false;
                    addMessage("hostname.UndecipherableTld");
                }

            } while (false);

            if (status == true && allowDNS) {
                result = true;
            }

        } else if (allowDNS == true) {
            addMessage("hostname.InvalidHostname");
            throw new ValidatorException(messages);
        }

        // Check input against local network name schema;
        Pattern regexLocal = Pattern.compile("^(([a-zA-Z0-9\\x2d]{1,63}\\x2e)*[a-zA-Z0-9\\x2d]{1,63}){1,254}$", Pattern.CASE_INSENSITIVE);
        boolean checkLocal = regexLocal.matcher(hostName).find();
        if (allowLocal && !status) {
            if (checkLocal) {
                result = true;
            } else {
                // If the input does not pass as a local network name, add a message
                result = false;
                addMessage("hostname.InvalidLocalName");
            }
        }


        // If local network names are not allowed, add a message
        if (checkLocal && !allowLocal && !status) {
            result = false;
            addMessage("hostname.LocalNameNotAllowed");
        }

        if (result == false) {
            throw new ValidatorException(messages);
        }

    }

    private void addMessage(String msg) {
        String bundlMsg = bundle.getString(msg);
        messages.add(new FacesMessage(FacesMessage.SEVERITY_ERROR, bundlMsg, bundlMsg));
    }

    /**
     * Returns a list of regex patterns for the matched TLD
     * @param tld
     * @return 
     */
    private List<String> getIdnRegexChars() {
        List<String> regexChars = new ArrayList<String>();
        regexChars.add("^[a-z0-9\\x2d]{1,63}$");
        Document doc = null;
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);

        try {
            InputStream validIdns = getClass().getClassLoader().getResourceAsStream("com/myapp/resources/validIDNs_1.xml");
            DocumentBuilder builder = factory.newDocumentBuilder();
            doc = builder.parse(validIdns);
            doc.getDocumentElement().normalize();
        } catch (SAXException ex) {
            Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex);
        } catch (ParserConfigurationException ex) {
            Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex);
        }

        // prepare XPath
        XPath xpath = XPathFactory.newInstance().newXPath();

        NodeList nodes = null;
        String xpathRoute = "//idn[tld=\'" + tld.toUpperCase() + "\']/pattern/text()";

        try {
            XPathExpression expr;
            expr = xpath.compile(xpathRoute);
            Object res = expr.evaluate(doc, XPathConstants.NODESET);
            nodes = (NodeList) res;
        } catch (XPathExpressionException ex) {
            Logger.getLogger(HostnameValidator.class.getName()).log(Level.SEVERE, null, ex);
        }


        for (int i = 0; i < nodes.getLength(); i++) {
            regexChars.add(nodes.item(i).getNodeValue());
        }

        return regexChars;
    }

    /**
     * Decode Punycode string
     * @param encoded
     * @return 
         */
    private String decodePunycode(String encoded) {
        Pattern regex = Pattern.compile("([^a-z0-9\\x2d]{1,10})", Pattern.CASE_INSENSITIVE);
        Matcher matcher = regex.matcher(encoded);
        boolean found = matcher.find();

        if (encoded.isEmpty() || found) {
            // no punycode encoded string, return as is
            addMessage("hostname.CannotDecodePunycode");
            throw new ValidatorException(messages);
        }

        int separator = encoded.lastIndexOf("-");
            List<Integer> decoded = new ArrayList<Integer>();
        if (separator > 0) {
            for (int x = 0; x < separator; ++x) {
                decoded.add((int) encoded.charAt(x));
            }
        } else {
            addMessage("hostname.CannotDecodePunycode");
            throw new ValidatorException(messages);
        }

        int lengthd = decoded.size();
        int lengthe = encoded.length();

        // decoding
        boolean init = true;
        int base = 72;
        int index = 0;
        int ch = 0x80;

        int indexeStart = (separator == 1) ? (separator + 1) : 0;
        for (int indexe = indexeStart; indexe < lengthe; ++lengthd) {
            int oldIndex = index;
            int pos = 1;
            for (int key = 36; true; key += 36) {
                int hex = (int) encoded.charAt(indexe++);
                int digit = (hex - 48 < 10) ? hex - 22
                        : ((hex - 65 < 26) ? hex - 65
                        : ((hex - 97 < 26) ? hex - 97
                        : 36));

                index += digit * pos;
                int tag = (key <= base) ? 1 : ((key >= base + 26) ? 26 : (key - base));
                if (digit < tag) {
                    break;
                }
                pos = (int) (pos * (36 - tag));
            }
            int delta = (int) (init ? ((index - oldIndex) / 700) : ((index - oldIndex) / 2));
            delta += (int) (delta / (lengthd + 1));
            int key;
            for (key = 0; delta > 910; key += 36) {
                delta = (int) (delta / 35);
            }
            base = (int) (key + 36 * delta / (delta + 38));
            init = false;
            ch += (int) (index / (lengthd + 1));
            index %= (lengthd + 1);
            if (lengthd > 0) {
                for (int i = lengthd; i > index; i--) {
                    decoded.set(i, decoded.get(i - 1));
                }
            }

            decoded.set(index++, ch);
        }

        // convert decoded ucs4 to utf8 string
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < decoded.size(); i++) {
            int value = decoded.get(i);
            if (value < 128) {
                sb.append((char) value);
            } else if (value < (1 << 11)) {
                sb.append((char) (192 + (value >> 6)));
                sb.append((char) (128 + (value & 63)));
            } else if (value < (1 << 16)) {
                sb.append((char) (224 + (value >> 12)));
                sb.append((char) (128 + ((value >> 6) & 63)));
                sb.append((char) (128 + (value & 63)));
            } else if (value < (1 << 21)) {
                sb.append((char) (240 + (value >> 18)));
                sb.append((char) (128 + ((value >> 12) & 63)));
                sb.append((char) (128 + ((value >> 6) & 63)));
                sb.append((char) (128 + (value & 63)));
            } else {
                addMessage("hostname.CannotDecodePunycode");
                throw new ValidatorException(messages);
            }
        }

        return sb.toString();

    }

    /**
     * Eliminates empty values from input array
     * @param data
     * @return 
     */
    private String[] verifyArray(String[] data) {
        List<String> result = new ArrayList<String>();
        for (String s : data) {
            if (!s.equals("")) {
                result.add(s);
            }
        }

        return result.toArray(new String[result.size()]);
    }
}

Ve farklı tld'ler için normal ifade desenlerine sahip geçerli bir IDNs.xml (dahil etmek için çok büyük :)

<idnlist>
    <idn>
        <tld>AC</tld>
        <pattern>^[\u002d0-9a-zà-öø-ÿāăąćĉċčďđēėęěĝġģĥħīįĵķĺļľŀłńņňŋőœŕŗřśŝşšţťŧūŭůűųŵŷźżž]{1,63}$</pattern>
    </idn>
    <idn>
        <tld>AR</tld>
        <pattern>^[\u002d0-9a-zà-ãç-êìíñ-õü]{1,63}$</pattern>
    </idn>
    <idn>
        <tld>AS</tld>
        <pattern>/^[\u002d0-9a-zà-öø-ÿāăąćĉċčďđēĕėęěĝğġģĥħĩīĭįıĵķĸĺļľłńņňŋōŏőœŕŗřśŝşšţťŧũūŭůűųŵŷźż]{1,63}$</pattern>
    </idn>
    <idn>
        <tld>AT</tld>
        <pattern>/^[\u002d0-9a-zà-öø-ÿœšž]{1,63}$</pattern>
    </idn>
    <idn>
        <tld>BIZ</tld>
        <pattern>^[\u002d0-9a-zäåæéöøü]{1,63}$</pattern>
        <pattern>^[\u002d0-9a-záéíñóúü]{1,63}$</pattern>
        <pattern>^[\u002d0-9a-záéíóöúüőű]{1,63}$</pattern>
    </id>
</idlist>

Bu yanıt, bariz nedenlerden dolayı artık geçerli değil. TLD doğrulamasını kaldırın ve İngilizce olmayan e-posta adreslerini kabul etmek istiyorsanız muhtemelen kabul edilebilir.
Christopher Schneider

3
public class Validations {

    private Pattern regexPattern;
    private Matcher regMatcher;

    public String validateEmailAddress(String emailAddress) {

        regexPattern = Pattern.compile("^[(a-zA-Z-0-9-\\_\\+\\.)]+@[(a-z-A-z)]+\\.[(a-zA-z)]{2,3}$");
        regMatcher   = regexPattern.matcher(emailAddress);
        if(regMatcher.matches()) {
            return "Valid Email Address";
        } else {
            return "Invalid Email Address";
        }
    }

    public String validateMobileNumber(String mobileNumber) {
        regexPattern = Pattern.compile("^\\+[0-9]{2,3}+-[0-9]{10}$");
        regMatcher   = regexPattern.matcher(mobileNumber);
        if(regMatcher.matches()) {
            return "Valid Mobile Number";
        } else {
            return "Invalid Mobile Number";
        }
    }

    public static void main(String[] args) {

        String emailAddress = "suryaprakash.pisay@gmail.com";
        String mobileNumber = "+91-9986571622";
        Validations validations = new Validations();
        System.out.println(validations.validateEmailAddress(emailAddress));
        System.out.println(validations.validateMobileNumber(mobileNumber));
    }
}

2

Bir e-posta adresinin geçerli olup olmadığını doğrulamak istiyorsanız, VRFY size bir şekilde yol gösterecektir. İntranet adreslerini (dahili siteler için e-posta adreslerini) doğrulamak için yararlı buldum . Ancak internet posta sunucuları için daha az yararlıdır (bu sayfanın üst kısmındaki uyarılara bakın)


2

Apache müşterilerinin çok sayıda alternatifi olmasına rağmen, uygulamaları en iyi ihtimalle ilkeldir ( Apache müşterilerinin uygulaması gibi ) ve hatta diğer durumlarda ölü olarak yanlıştır.

Ayrıca sözde basit 'kısıtlayıcı olmayan' regex uzak kalmak istiyorum; böyle bir şey yok. Örneğin @ bağlama göre birçok kez izin verilir , gerekli olanın orada olduğunu nereden biliyorsunuz? Basit normal ifade, e-postanın geçerli olması gerekse bile bunu anlamaz. Daha karmaşık her şey hataya açık hale gelir veya hatta gizli performans katilleri içerir . Nasıl böyle bir şey korumak için gidiyoruz bu ?

Fark ettiğim tek kapsamlı RFC uyumlu normal ifade tabanlı doğrulayıcı e-posta-rfc2822-doğrulayıcıdır ve Dragons.java adı verilen 'rafine' normal ifadesiyle . Bununla birlikte, modern ihtiyaçlar için yeterince uygun olmasına rağmen, yalnızca eski RFC-2822 spesifikasyonunu destekler (RFC-5322 , günlük kullanım durumları için zaten kapsam dışı alanlarda güncellenir ).

Ama gerçekten istediğiniz şey, bir dizeyi düzgün bir şekilde ayrıştıran ve RFC dilbilgisine göre bileşen yapısına ayıran bir lexer . EmailValidator4J bu konuda umut vaat ediyor, ancak yine de genç ve sınırlı.

Sahip olduğunuz diğer bir seçenek de Mailgun'un savaşta test edilmiş doğrulama web hizmeti veya Mailboxlayer API'sı gibi bir web hizmetini kullanmaktır (ilk Google sonuçlarını aldınız ). Kesinlikle RFC uyumlu değildir, ancak modern ihtiyaçlar için yeterince iyi çalışır.


1

Neyi doğrulamak istiyorsun? Email adresi?

E-posta adresi yalnızca biçim uygunluğu açısından kontrol edilebilir. Standarda bakın: RFC2822 . Bunu yapmanın en iyi yolu düzenli bir ifadedir. Bir e-posta göndermeden gerçekten var olup olmadığını asla bilemezsiniz.

Ortak doğrulayıcıyı kontrol ettim. Bir org.apache.commons.validator.EmailValidator sınıfı içerir. İyi bir başlangıç ​​noktası gibi görünüyor.



@ User2813274 ile anlaşın, spagetti regex değil, uygun bir lexer istiyorsunuz.
Benny Bottema

1

Mevcut Apache Commons Validator sürümü 1.3.1'dir .

Doğrulayan sınıf org.apache.commons.validator.EmailValidator'dır. Emekli bir Jakarta ORO projesinden olan org.apache.oro.text.perl.Perl5Util için bir ithalatı var .

BTW, 1.4 sürümü olduğunu buldum, işte API belgeleri . On sitesinde şöyle der: ": 2008 05 Mart | Versiyon: Son Yayın 1.4-SNAPSHOT", ama bu son değil. Kendinizi kurmanın tek yolu (ancak bu bir RELEASE değil, bir anlık görüntüdür) ve kullanın veya buradan indirin . Bu, 1.4'ün üç yıldır (2008-2011) final yapılmadığı anlamına geliyor. Bu Apache'nin tarzında değil. Daha iyi bir seçenek arıyorum, ancak çok benimsenen bir seçenek bulamadım. İyi test edilmiş bir şey kullanmak istiyorum, herhangi bir hataya çarpmak istemiyorum.


1.4 SNAPSHOT ayrıca Jakarta ORO gerektirir. Apache Commons Validator benim için uygun değil.
sis

Sonunda Dr.Vet'i seçti. Cumpanasu
mist

1
Apache Commons doğrulayıcısının iyi çalıştığını kabul ediyorum, ancak arama başına 3 ms'den fazla oldukça yavaş olduğunu düşünüyorum.
Nic Cottrell

Performans benim için o kadar önemli değil.
sis

mevcut gövde SNAPSHOT (şu andan itibaren SVN REV 1227719) artık ORO gibi harici bağımlılıklara sahip değil - artık tüm doğrulama modülüne bile ihtiyacınız yok - dört sınıf org.apache.commons.validator.routines.EmailValidator, InetAddressValidator, DomainValidator ve RegexValidator tek başına ayakta kalabiliyor
Jörg

0

Uzunluğunu da kontrol etmek isteyebilirsiniz - e-postalar maksimum 254 karakter uzunluğundadır. Apache ortak doğrulayıcısı kullanıyorum ve bunu kontrol etmiyor.


RFC 2821 türü (bölüm 4.5.3.1) local-part64 domainuzunluğunu ve 255 uzunluğunu belirtir. (Başka bir yazılım tarafından daha uzun süre reddedilebileceğini söylüyorlar.)
sarnold

-2

E-posta adresine bir e-posta göndermek ve bir yanıt beklemek zorunda kalmadıkça, mükemmel kütüphaneler veya bunu kendiniz yapmanın yolları yoktur (bu bir seçenek olmayabilir). Buradan http://blog.logichigh.com/2010/09/02/validating-an-e-mail-address/ şeklinde bir öneri kullanarak ve Java'da çalışacak şekilde kodu ayarladım.

public static boolean isValidEmailAddress(String email) {
    boolean stricterFilter = true; 
    String stricterFilterString = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    String laxString = ".+@.+\\.[A-Za-z]{2}[A-Za-z]*";
    String emailRegex = stricterFilter ? stricterFilterString : laxString;
    java.util.regex.Pattern p = java.util.regex.Pattern.compile(emailRegex);
    java.util.regex.Matcher m = p.matcher(email);
    return m.matches();
}

-2

Bu en iyi yöntemdir:

public static boolean isValidEmail(String enteredEmail){
        String EMAIL_REGIX = "^[\\\\w!#$%&’*+/=?`{|}~^-]+(?:\\\\.[\\\\w!#$%&’*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\\\.)+[a-zA-Z]{2,6}$";
        Pattern pattern = Pattern.compile(EMAIL_REGIX);
        Matcher matcher = pattern.matcher(enteredEmail);
        return ((!enteredEmail.isEmpty()) && (enteredEmail!=null) && (matcher.matches()));
    }

Kaynaklar: - http://howtodoinjava.com/2014/11/11/java-regex-validate-email-address/

http://www.rfc-editor.org/rfc/rfc5322.txt


-2

Başka bir seçenek de, Hazırda Bekletme e-posta doğrulayıcısını , ek açıklamayı @Emailkullanarak veya doğrulayıcı sınıfını programlı olarak kullanmaktır:

import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator; 

class Validator {
    // code
    private boolean isValidEmail(String email) {
        EmailValidator emailValidator = new EmailValidator();
        return emailValidator.isValid(email, null);
    }

}

Neden inişli çıkışlı? Hibernate Validator tarafından kullanılanla aynı sınıftır.
Dherik

-3

Heres pragmatik yaklaşımım, burada sadece RFC'den izin verilen karakterleri kullanarak makul farklı blah @ etki alanı adresleri istiyorum. Adresler önceden küçük harfe dönüştürülmelidir.

public class EmailAddressValidator {

    private static final String domainChars = "a-z0-9\\-";
    private static final String atomChars = "a-z0-9\\Q!#$%&'*+-/=?^_`{|}~\\E";
    private static final String emailRegex = "^" + dot(atomChars) + "@" + dot(domainChars) + "$";
    private static final Pattern emailPattern = Pattern.compile(emailRegex);

    private static String dot(String chars) {
        return "[" + chars + "]+(?:\\.[" + chars + "]+)*";
    }

    public static boolean isValidEmailAddress(String address) {
        return address != null && emailPattern.matcher(address).matches();
    }

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.