Các thư viện xác thực địa chỉ email tốt cho Java là gì? Có bất kỳ lựa chọn thay thế cho trình xác nhận commons ?
Các thư viện xác thực địa chỉ email tốt cho Java là gì? Có bất kỳ lựa chọn thay thế cho trình xác nhận commons ?
Câu trả lời:
Apache Commons thường được biết đến như một dự án vững chắc. Tuy nhiên, hãy nhớ rằng, bạn vẫn sẽ phải gửi email xác minh đến địa chỉ nếu bạn muốn đảm bảo đó là email thực và chủ sở hữu muốn sử dụng nó trên trang web của bạn.
EDIT : Có một lỗi trong đó quá hạn chế về tên miền, khiến nó không chấp nhận các email hợp lệ từ các TLD mới.
Lỗi này đã được giải quyết vào ngày 03 tháng 1/15 02:48 trong phiên bản commons-validator phiên bản 1.4.1
EmailValidator
lớp Apache không gửi thông báo email để xác minh.
Sử dụng gói email java chính thức là dễ nhất:
public static boolean isValidEmailAddress(String email) {
boolean result = true;
try {
InternetAddress emailAddr = new InternetAddress(email);
emailAddr.validate();
} catch (AddressException ex) {
result = false;
}
return result;
}
.
, .com
, com.
, abc
và 123
. Ngoài ra, việc thêm khoảng trắng ở đầu hoặc cuối cũng không làm mất hiệu lực của chuỗi. Bạn là thẩm phán!
Trình xác thực Apache Commons có thể được sử dụng như được đề cập trong các câu trả lời khác.
tệp pom.xml:
<dependency>
<groupId>commons-validator</groupId>
<artifactId>commons-validator</artifactId>
<version>1.4.1</version>
</dependency>
bản dựng.
compile 'commons-validator:commons-validator:1.4.1'
Nhập khẩu:
import org.apache.commons.validator.routines.EmailValidator;
Mật mã:
String email = "myName@example.com";
boolean valid = EmailValidator.getInstance().isValid(email);
và cho phép địa chỉ địa phương
boolean allowLocal = true;
boolean valid = EmailValidator.getInstance(allowLocal).isValid(email);
Trả lời muộn, nhưng tôi nghĩ nó đơn giản và xứng đáng:
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();
}
Các trường hợp thử nghiệm :
Đối với mục đích sản xuất, xác thực tên miền nên được thực hiện theo mạng.
Nếu bạn đang cố gắng thực hiện xác nhận mẫu nhận được từ máy khách hoặc chỉ xác thực bằng bean - hãy giữ cho đơn giản. Tốt hơn là thực hiện xác thực email lỏng lẻo hơn là thực hiện nghiêm ngặt và từ chối một số người, (ví dụ: khi họ đang cố gắng đăng ký dịch vụ web của bạn). Với hầu hết mọi thứ được cho phép trong phần tên người dùng của email và rất nhiều tên miền mới được thêm vào mỗi tháng (ví dụ: công ty, .entreprise, .estate), sẽ an toàn hơn nếu không bị hạn chế:
Pattern pattern = Pattern.compile("^.+@.+\\..+$");
Matcher matcher = pattern.matcher(email);
Cuối câu hỏi, ở đây, nhưng: Tôi duy trì một lớp học tại địa chỉ này: http://lacinato.com/cm/software/emailrelated/emailaddress
Nó dựa trên lớp của Les Hazlewood, nhưng có nhiều cải tiến và sửa một vài lỗi. Giấy phép Apache.
Tôi tin rằng nó là trình phân tích cú pháp email có khả năng nhất trong Java và tôi chưa thấy một trình duyệt nào có khả năng hơn trong bất kỳ ngôn ngữ nào, mặc dù có thể có một trình duyệt ngoài đó. Nó không phải là trình phân tích cú pháp kiểu lexer, nhưng sử dụng một số biểu thức java phức tạp và do đó không hiệu quả như nó có thể, nhưng công ty của tôi đã phân tích tốt hơn 10 tỷ địa chỉ trong thế giới thực với nó: nó chắc chắn có thể sử dụng được trong hiệu suất cao tình hình. Có thể mỗi năm một lần nó sẽ đánh vào một địa chỉ gây ra lỗi tràn ngăn xếp regex (một cách thích hợp), nhưng đây là những địa chỉ spam dài hàng trăm hoặc hàng nghìn ký tự với nhiều dấu ngoặc kép và dấu ngoặc đơn và tương tự.
RFC 2822 và các thông số kỹ thuật liên quan thực sự khá dễ dãi về mặt địa chỉ email, vì vậy một lớp như thế này là quá mức cần thiết cho hầu hết các mục đích sử dụng. Ví dụ: sau đây là một địa chỉ hợp pháp, theo thông số kỹ thuật, khoảng trắng và tất cả:
"<bob \" (here) " < (hi there) "bob(the man)smith" (hi) @ (there) example.com (hello) > (again)
Không có máy chủ thư nào cho phép điều đó, nhưng lớp này có thể phân tích cú pháp (và viết lại thành dạng có thể sử dụng được).
Chúng tôi thấy các tùy chọn trình phân tích cú pháp email Java hiện tại không đủ bền (có nghĩa là tất cả chúng không thể phân tích một số địa chỉ hợp lệ), vì vậy chúng tôi đã tạo lớp này.
Mã này được ghi chép tốt và có nhiều tùy chọn dễ thay đổi để cho phép hoặc không cho phép một số biểu mẫu email nhất định. Nó cũng cung cấp rất nhiều phương thức để truy cập vào một số phần nhất định của địa chỉ (bên trái, bên phải, tên cá nhân, nhận xét, v.v.), để phân tích / xác thực các tiêu đề danh sách hộp thư, để phân tích / xác thực đường dẫn trở lại (là duy nhất trong số các tiêu đề), v.v.
Mã như được viết có một phụ thuộc javamail, nhưng thật dễ dàng để loại bỏ nếu bạn không muốn chức năng nhỏ mà nó cung cấp.
Tôi chỉ tự hỏi tại sao không ai nghĩ ra @Email
từ các ràng buộc bổ sung của Trình xác thực Hibernate. Trình xác nhận chính nó là EmailValidator
.
Les Hazlewood đã viết một lớp trình xác nhận email tuân thủ RFC 2822 rất kỹ lưỡng bằng cách sử dụng các biểu thức chính quy Java. Bạn có thể tìm thấy nó tại http: // www . Meatazlewood.com/?p=23 . Tuy nhiên, tính kỹ lưỡng của nó (hoặc triển khai Java RE) dẫn đến không hiệu quả - đọc các nhận xét về thời gian phân tích cú pháp cho các địa chỉ dài.
Tôi đã chuyển một số mã trong Zend_Validator_Email:
@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();
}
}
Với trình xác nhận tên máy chủ như sau:
@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()]);
}
}
Và một tệp IDIDNs hợp lệ với các mẫu biểu thức chính quy cho các tld khác nhau (quá lớn để bao gồm :)
<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>
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));
}
}
Nếu bạn đang tìm cách xác minh xem một địa chỉ email có hợp lệ hay không, thì VRFY sẽ giúp bạn tìm ra cách nào đó. Tôi thấy nó hữu ích cho việc xác thực mạng nội bộ địa chỉ (nghĩa là địa chỉ email cho các trang web nội bộ). Tuy nhiên, nó ít hữu ích hơn cho các máy chủ thư internet (xem phần lưu ý ở đầu trang này)
Mặc dù có nhiều lựa chọn thay thế cho commons Apache, nhưng việc triển khai của chúng là thô sơ nhất (như cách triển khai của Apache commons chính ) và thậm chí đã sai trong các trường hợp khác.
Tôi cũng sẽ tránh xa cái gọi là regex đơn giản 'không hạn chế'; không có những điều như vậy. Ví dụ @ được phép nhiều lần tùy thuộc vào ngữ cảnh, làm thế nào để bạn biết cái được yêu cầu ở đó? Regex đơn giản sẽ không hiểu nó, mặc dù email phải hợp lệ. Bất cứ điều gì phức tạp hơn đều trở nên dễ bị lỗi hoặc thậm chí có chứa các sát thủ hiệu suất ẩn . Làm thế nào bạn sẽ duy trì một cái gì đó như thế này ?
Trình xác nhận dựa trên regex tuân thủ RFC toàn diện duy nhất mà tôi biết là trình xác thực email-rfc2822 với biểu thức chính thức 'tinh chỉnh' của nó được đặt tên thích hợp Dragons.java . Mặc dù vậy, nó chỉ hỗ trợ thông số RFC-2822 cũ hơn , mặc dù đủ thích hợp cho các nhu cầu hiện đại ( cập nhật RFC-5322 nó trong các khu vực đã vượt quá phạm vi cho các trường hợp sử dụng hàng ngày).
Nhưng thực sự những gì bạn muốn là một lexer phân tích chính xác một chuỗi và chia nó thành cấu trúc thành phần theo ngữ pháp RFC. EmailValidator4J có vẻ đầy hứa hẹn về vấn đề đó, nhưng vẫn còn non trẻ và hạn chế.
Một tùy chọn khác mà bạn có là sử dụng dịch vụ web như dịch vụ web xác thực được kiểm tra trong trận chiến của Mailgun hoặc API Mailboxlayer (vừa lấy kết quả Google đầu tiên). Nó không hoàn toàn tuân thủ RFC, nhưng hoạt động đủ tốt cho các nhu cầu hiện đại.
Bạn muốn xác nhận những gì? Địa chỉ email?
Địa chỉ email chỉ có thể được kiểm tra sự phù hợp định dạng của nó. Xem tiêu chuẩn: RFC2822 . Cách tốt nhất để làm điều đó là một biểu thức thông thường. Bạn sẽ không bao giờ biết nếu thực sự tồn tại mà không gửi email.
Tôi đã kiểm tra trình xác nhận commons. Nó chứa một lớp org.apache.commons.validator.EmailValidator. Có vẻ là một điểm khởi đầu tốt.
Phiên bản Trình xác thực Apache Commons hiện tại là 1.3.1 .
Lớp xác nhận là org.apache.commons.validator.EmailValidator. Nó có một bản nhập cho org.apache.oro.text.perl.Perl5Util từ một dự án ORO Jakarta đã nghỉ hưu .
BTW, tôi thấy rằng có một phiên bản 1.4, đây là các tài liệu API . Trên trang web có ghi: "Xuất bản lần cuối: ngày 5 tháng 3 năm 2008 | Phiên bản: 1.4-SNAPSHOT", nhưng đó không phải là bản cuối cùng. Chỉ có cách xây dựng bản thân (nhưng đây là ảnh chụp nhanh, không phải ĐÁNG TIN CẬY) và sử dụng hoặc tải xuống từ đây . Điều này có nghĩa là 1.4 đã không được thực hiện cuối cùng trong ba năm (2008-2011). Đây không phải là phong cách của Apache. Tôi đang tìm kiếm một lựa chọn tốt hơn, nhưng không tìm thấy một lựa chọn nào được chấp nhận. Tôi muốn sử dụng một cái gì đó đã được thử nghiệm tốt, không muốn gặp bất kỳ lỗi nào.
Bạn cũng có thể muốn kiểm tra độ dài - email dài tối đa là 254 ký tự. Tôi sử dụng trình xác nhận apache commons và nó không kiểm tra điều này.
local-part
chiều dài 64 và domain
chiều dài 255. (Họ nói rằng thời gian dài hơn được cho phép có thể bị từ chối bởi phần mềm khác.)
Dường như không có bất kỳ thư viện hay cách hoàn hảo nào để tự làm việc này, trừ khi bạn phải gửi email đến địa chỉ email và chờ phản hồi (mặc dù điều này có thể không phải là một lựa chọn). Tôi đã kết thúc bằng cách sử dụng một đề xuất từ đây http://blog.logichigh.com/2010/09/02/validating-an-e-mail-address/ và điều chỉnh mã để nó hoạt động trong Java.
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();
}
Đây là phương pháp tốt nhất:
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()));
}
Nguồn: - http://howtodoinjava.com/2014/11/11/java-regex-validate-email-address/
Một tùy chọn khác là sử dụng trình xác nhận email Hibernate , sử dụng chú thích @Email
hoặc sử dụng lớp trình xác nhận theo chương trình, như:
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);
}
}
Đây là cách tiếp cận thực dụng của tôi, nơi tôi chỉ muốn các địa chỉ miền blah @ khác biệt hợp lý bằng cách sử dụng các ký tự được phép từ RFC. Địa chỉ phải được chuyển đổi thành chữ thường trước.
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();
}
}