What is the best Java email address validation method? [closed] - validation
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 5 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What are the good email address validation libraries for Java? Are there any alternatives to commons validator?
Using the official java email package is the easiest:
public static boolean isValidEmailAddress(String email) {
boolean result = true;
try {
InternetAddress emailAddr = new InternetAddress(email);
emailAddr.validate();
} catch (AddressException ex) {
result = false;
}
return result;
}
Apache Commons is generally known as a solid project. Keep in mind, though, you'll still have to send a verification email to the address if you want to ensure it's a real email, and that the owner wants it used on your site.
EDIT: There was a bug where it was too restrictive on domain, causing it to not accept valid emails from new TLDs.
This bug was resolved on 03/Jan/15 02:48 in commons-validator version 1.4.1
Apache Commons validator can be used as mentioned in the other answers.
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'
The import:
import org.apache.commons.validator.routines.EmailValidator;
The code:
String email = "myName#example.com";
boolean valid = EmailValidator.getInstance().isValid(email);
and to allow local addresses
boolean allowLocal = true;
boolean valid = EmailValidator.getInstance(allowLocal).isValid(email);
Late answer, but I think it is simple and worthy:
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 Cases:
For production purpose, Domain Name validations should be performed network-wise.
If you are trying to do a form validation received from the client, or just a bean validation - keep it simple.
It's better to do a loose email validation rather than to do a strict one and reject some people, (e.g. when they are trying to register for your web service).
With almost anything allowed in the username part of the email and so many new domains being added literally every month (e.g. .company, .entreprise, .estate), it's safer not to be restrictive:
Pattern pattern = Pattern.compile("^.+#.+\\..+$");
Matcher matcher = pattern.matcher(email);
Late to the question, here, but: I maintain a class at this address: http://lacinato.com/cm/software/emailrelated/emailaddress
It is based on Les Hazlewood's class, but has numerous improvements and fixes a few bugs. Apache license.
I believe it is the most capable email parser in Java, and I have yet to see one more capable in any language, though there may be one out there. It's not a lexer-style parser, but uses some complicated java regex, and thus is not as efficient as it could be, but my company has parsed well over 10 billion real-world addresses with it: it's certainly usable in a high-performance situation. Maybe once a year it'll hit an address that causes a regex stack overflow (appropriately), but these are spam addresses which are hundreds or thousands of characters long with many many quotes and parenthesis and the like.
RFC 2822 and the related specs are really quite permissive in terms of email addresses, so a class like this is overkill for most uses. For example, the following is a legitimate address, according to spec, spaces and all:
"<bob \" (here) " < (hi there) "bob(the man)smith" (hi) # (there) example.com (hello) > (again)
No mail server would allow that, but this class can parse it (and rewrite it to a usable form).
We found the existing Java email parser options to be insufficiently durable (meaning, all of them could not parse some valid addresses), so we created this class.
The code is well-documented and has a lot of easy-to-change options to allow or disallow certain email forms. It also provides a lot of methods to access certain parts of the address (left-hand side, right-hand side, personal names, comments, etc), to parse/validate mailbox-list headers, to parse/validate the return-path (which is unique among the headers), and so forth.
The code as written has a javamail dependency, but it's easy to remove if you don't want the minor functionality it provides.
I'm just wondering why nobody came up with #Email from Hibernate Validator's additional constraints. The validator itself is EmailValidator.
Les Hazlewood has written a very thorough RFC 2822 compliant email validator class using Java regular expressions. You can find it at http://www.leshazlewood.com/?p=23. However, its thoroughness (or the Java RE implementation) leads to inefficiency - read the comments about parsing times for long addresses.
I ported some of the code in 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();
}
}
With a hostname validator as follows:
#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()]);
}
}
And a validIDNs.xml with regex patterns for the different tlds (too big to include:)
<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));
}
}
If you're looking to verify whether an email address is valid, then VRFY will get you some of the way. I've found it's useful for validating intranet addresses (that is, email addresses for internal sites). However it's less useful for internet mail servers (see the caveats at the top of this page)
Although there are many alternatives to Apache commons, their implementations are rudimentary at best (like Apache commons' implementation itself) and even dead wrong in other cases.
I'd also stay away from so called simple 'non-restrictive' regex; there's no such thing. For example # is allowed multiple times depending on context, how do you know the required one is there? Simple regex won't understand it, even though the email should be valid. Anything more complex becomes error-prone or even contain hidden performance killers. How are you going to maintain something like this?
The only comprehensive RFC compliant regex based validator I'm aware of is email-rfc2822-validator with its 'refined' regex appropriately named Dragons.java. It supports only the older RFC-2822 spec though, although appropriate enough for modern needs (RFC-5322 updates it in areas already out of scope for daily use cases).
But really what you want is a lexer that properly parses a string and breaks it up into the component structure according to the RFC grammar. EmailValidator4J seems promising in that regard, but is still young and limited.
Another option you have is using a webservice such as Mailgun's battle-tested validation webservice or Mailboxlayer API (just took the first Google results). It is not strictly RFC compliant, but works well enough for modern needs.
What do you want to validate? The email address?
The email address can only be checked for its format conformance. See the standard: RFC2822. Best way to do that is a regular expression. You will never know if really exists without sending an email.
I checked the commons validator. It contains an org.apache.commons.validator.EmailValidator class. Seems to be a good starting point.
Current Apache Commons Validator version is 1.3.1.
Class that validates is org.apache.commons.validator.EmailValidator. It has an import for org.apache.oro.text.perl.Perl5Util which is from a retired Jakarta ORO project.
BTW, I found that there is a 1.4 version, here are the API docs. On the site it says: "Last Published: 05 March 2008 | Version: 1.4-SNAPSHOT", but that's not final. Only way to build yourself (but this is a snapshot, not RELEASE) and use, or download from here. This means 1.4 has not been made final for three years (2008-2011). This is not in Apache's style.
I'm looking for a better option, but didn't find one that is very adopted. I want to use something that is well tested, don't want to hit any bugs.
You may also want to check for the length - emails are a maximum of 254 chars long. I use the apache commons validator and it doesn't check for this.
There don't seem to be any perfect libraries or ways to do this yourself, unless you have to time to send an email to the email address and wait for a response (this might not be an option though). I ended up using a suggestion from here http://blog.logichigh.com/2010/09/02/validating-an-e-mail-address/ and adjusting the code so it would work in 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();
}
This is the best method:
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()));
}
Sources:-
http://howtodoinjava.com/2014/11/11/java-regex-validate-email-address/
http://www.rfc-editor.org/rfc/rfc5322.txt
Another option is use the Hibernate email validator, using the annotation #Email or using the validator class programatically, like:
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);
}
}
Heres my pragmatic approach, where I just want reasonable distinct blah#domain addresses using the allowable characters from the RFC. Addresses must be converted to lowercase beforehand.
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();
}
}
Related
how to print image to thermal printer in kotlin
i already able to print text using kotlin to thermal printer, but im still dont know how to print image to thermal printer in kotlin. please give me sample printing image to thermal printer in kotlin.i already search for the topics, but it written in java, i doesnt know java very much thanks for the help private fun p1() { val namaToko = "Rose Medical" val alamatToko = "Pramuka raya no.1 Jakarta Timur" val telp = "021-85901642" val enter = "\n" val strip = "-" val rp ="Rp." val ex = " X " val textTotal = "Total Rp:" val ppnTv = "PPN :Rp." val chargeTv ="Charge :Rp." val totalTv = "Total Belanja :Rp." val scope = CoroutineScope(Dispatchers.IO) scope.launch { // chunks1 try{ writeWithFormat(namaToko.toByteArray(),Formatter().get(),Formatter.centerAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(alamatToko.toByteArray(),Formatter().get(),Formatter.centerAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(telp.toByteArray(),Formatter().get(),Formatter.centerAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) }catch (e: Exception) { Log.e("PrintActivity", "Exe ", e) } // chunks2 for(pointer in salesBody.indices){ try { val merk = salesBody[pointer].merk writeWithFormat(merk!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign()) val barang = salesBody[pointer].namaBrg writeWithFormat(barang!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) val varian = salesBody[pointer].varian writeWithFormat(varian!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(rp.toByteArray(),Formatter().get(),Formatter.leftAlign()) val harga = ValidNumber().deciformat(salesBody[pointer].hargaJual.toString()) writeWithFormat(harga.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(ex.toByteArray(),Formatter().get(),Formatter.leftAlign()) val jumlah = ValidNumber().deciformat(salesBody[pointer].qty.toString()) writeWithFormat(jumlah.toByteArray(),Formatter().get(),Formatter.leftAlign()) val satuan = salesBody[pointer].unit writeWithFormat(satuan!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(textTotal.toByteArray(),Formatter().get(),Formatter.rightAlign()) val total = ValidNumber().deciformat(salesBody[pointer].total.toString()) writeWithFormat(total.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) }catch (e: Exception) { Log.e("PrintActivity", "Exe ", e) } } // chunks3 try{ writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) val tanggal = salesHeader[0].tanggal writeWithFormat(tanggal!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign()) val jam = salesHeader[0].jam writeWithFormat(jam!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(strip.toByteArray(),Formatter().get(),Formatter.leftAlign()) val idTag= salesHeader[0].idTag writeWithFormat(idTag!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) val payment= salesHeader[0].payment writeWithFormat(payment!!.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.leftAlign()) writeWithFormat(ppnTv.toByteArray(),Formatter().get(),Formatter.rightAlign()) val ppnValue = ValidNumber().deciformat(salesHeader[0].ppn.toString()) writeWithFormat(ppnValue.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(chargeTv.toByteArray(),Formatter().get(),Formatter.rightAlign()) val chargeValue = ValidNumber().deciformat(salesHeader[0].charge.toString()) writeWithFormat(chargeValue.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(totalTv.toByteArray(),Formatter().get(),Formatter.rightAlign()) var totalValue = ValidNumber().deciformat(salesHeader[0].allTotal.toString()) writeWithFormat(totalValue.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) writeWithFormat(enter.toByteArray(),Formatter().get(),Formatter.rightAlign()) }catch (e: Exception) { Log.e("PrintActivity", "Exe ", e) } } } //print code class Formatter { /** The format that is being build on */ private val mFormat: ByteArray init { // Default: mFormat = byteArrayOf(27, 33, 0) } /** * Method to get the Build result * * #return the format */ fun get(): ByteArray { return mFormat } fun bold(): Formatter { // Apply bold: mFormat[2] = (0x8 or mFormat[2].toInt()).toByte() return this } fun small(): Formatter { mFormat[2] = (0x1 or mFormat[2].toInt()).toByte() return this } fun height(): Formatter { mFormat[2] = (0x10 or mFormat[2].toInt()).toByte() return this } fun width(): Formatter { mFormat[2] = (0x20 or mFormat[2].toInt()).toByte() return this } fun underlined(): Formatter { mFormat[2] = (0x80 or mFormat[2].toInt()).toByte() return this } companion object { fun rightAlign(): ByteArray { return byteArrayOf(0x1B, 'a'.code.toByte(), 0x02) } fun leftAlign(): ByteArray { return byteArrayOf(0x1B, 'a'.code.toByte(), 0x00) } fun centerAlign(): ByteArray { return byteArrayOf(0x1B, 'a'.code.toByte(), 0x01) } } }//last fun writeWithFormat(buffer: ByteArray, pFormat: ByteArray?, pAlignment: ByteArray?): Boolean { val mmOutStream: OutputStream = mBluetoothSocket.outputStream return try { // Notify printer it should be printed with given alignment: mmOutStream.write(pAlignment) // Notify printer it should be printed in the given format: mmOutStream.write(pFormat) // Write the actual data: mmOutStream.write(buffer, 0, buffer.size) // Share the sent message back to the UI Activity //App.getInstance().getHandler().obtainMessage(MESSAGE_WRITE, buffer.size, -1, buffer).sendToTarget() true } catch (e: IOException) { Log.e(TAG, "Exception during write", e) false } } //print code close
Using Thermal Printer repo references, I managed to print image to Bluetooth thermal printer. Make sure to use a proper black and white image to print. Here is the piece of code I used to make a java class --BitmapHelper.java. public class BitmapHelper { private static String[] binaryArray = { "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111" }; public static byte[] decodeBitmap(Bitmap bmp){ //Bitmap bmp = Bitmap.createScaledBitmap(bitmap, 50, 50, false); int maxWidth = 350; int bmpWidth = bmp.getWidth(); int bmpHeight = bmp.getHeight(); if(bmpWidth > maxWidth){ float aspectRatio = bmp.getWidth() / (float) bmp.getHeight(); bmpWidth = maxWidth; bmpHeight = Math.round(bmpWidth / aspectRatio); bmp = Bitmap.createScaledBitmap(bmp, bmpWidth, bmpHeight, false); } List<String> list = new ArrayList<>(); //binaryString list StringBuffer sb; int zeroCount = bmpWidth % 8; StringBuilder zeroStr = new StringBuilder(); if (zeroCount > 0) { for (int i = 0; i < (8 - zeroCount); i++) { zeroStr.append("0"); } } for (int i = 0; i < bmpHeight; i++) { sb = new StringBuffer(); for (int j = 0; j < bmpWidth; j++) { int color = bmp.getPixel(j, i); int r = (color >> 16) & 0xff; int g = (color >> 8) & 0xff; int b = color & 0xff; // if color close to white,bit='0', else bit='1' if (r > 160 && g > 160 && b > 160) sb.append("0"); else sb.append("1"); } if (zeroCount > 0) { sb.append(zeroStr); } list.add(sb.toString()); } List<String> bmpHexList = binaryListToHexStringList(list); String commandHexString = "1D763000"; String widthHexString = Integer .toHexString(bmpWidth % 8 == 0 ? bmpWidth / 8 : (bmpWidth / 8 + 1)); if (widthHexString.length() > 2) { Log.e("decodeBitmap error", " width is too large"); return null; } else if (widthHexString.length() == 1) { widthHexString = "0" + widthHexString; } widthHexString = widthHexString + "00"; String heightHexString = Integer.toHexString(bmpHeight); if (heightHexString.length() > 2) { Log.e("decodeBitmap error", " height is too large"); return null; } else if (heightHexString.length() == 1) { heightHexString = "0" + heightHexString; } heightHexString = heightHexString + "00"; List<String> commandList = new ArrayList<>(); commandList.add(commandHexString+widthHexString+heightHexString); commandList.addAll(bmpHexList); return hexList2Byte(commandList); } private static List<String> binaryListToHexStringList(List<String> list) { List<String> hexList = new ArrayList<String>(); for (String binaryStr : list) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < binaryStr.length(); i += 8) { String str = binaryStr.substring(i, i + 8); String hexString = myBinaryStrToHexString(str); sb.append(hexString); } hexList.add(sb.toString()); } return hexList; } private static String myBinaryStrToHexString(String binaryStr) { StringBuilder hex = new StringBuilder(); String f4 = binaryStr.substring(0, 4); String b4 = binaryStr.substring(4, 8); String hexStr = "0123456789ABCDEF"; for (int i = 0; i < binaryArray.length; i++) { if (f4.equals(binaryArray[i])) hex.append(hexStr.substring(i, i + 1)); } for (int i = 0; i < binaryArray.length; i++) { if (b4.equals(binaryArray[i])) hex.append(hexStr.substring(i, i + 1)); } return hex.toString(); } private static byte[] hexList2Byte(List<String> list) { List<byte[]> commandList = new ArrayList<byte[]>(); for (String hexStr : list) { commandList.add(hexStringToBytes(hexStr)); } return sysCopy(commandList); } private static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } private static byte[] sysCopy(List<byte[]> srcArrays) { int len = 0; for (byte[] srcArray : srcArrays) { len += srcArray.length; } byte[] destArray = new byte[len]; int destLen = 0; for (byte[] srcArray : srcArrays) { System.arraycopy(srcArray, 0, destArray, destLen, srcArray.length); destLen += srcArray.length; } return destArray; } private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } } Then I use it in the print activity: private fun p2(){ val convertBmp : Bitmap convertBmp = BitmapFactory.decodeResource(getResources(),com.example.ronibluetooth.R.drawable.poly) val decodeBmp = BitmapHelper.decodeBitmap(convertBmp) val scope = CoroutineScope(Dispatchers.IO) scope.launch { try { val os =mBluetoothSocket.outputStream os.write(decodeBmp,0,decodeBmp.size) } catch (e: Exception) { Log.e("PrintActivity", "Exe ", e) } } } image to print result print
Is there a way to avoid the truncation of attached properties when using Appcenter with Xamarin?
Here's my code: Crashes.TrackError(ex, new Dictionary<string, string> { {"RunQuery", "Exception"}, {"sql", s }, {"Device Model", DeviceInfo.Model }, {"Exception", ex.ToString()} }); Everything works but I find that Appcenter limits the length of the parameters to 125 characters so it's useless for me as I can never see all of the sql or the ex string. Has anyone found a way to get around this?
I ran into the same problem. My solution was to break my string into groups of 125 character strings and iterate through while logging. I chatted with AppCenter support. They have no way of extending this length currently. Here is a scrubbed version of my code: var tokenChunks = LoggingHelper.SplitBy(extremelyLongString, 120); string title = "Long string here"; var props = new Dictionary<string, string>(); int item = 0; foreach(string chunk in tokenChunks) { string chunkIndex = string.Format("item: {0}", item++); props.Add(chunkIndex, chunk); } Analytics.TrackEvent(title, props); Where the LoggingHelper class is: public static class LoggingHelper { public static IEnumerable<string> SplitBy(this string str, int chunkLength) { if (String.IsNullOrEmpty(str)) throw new ArgumentException(); if (chunkLength < 1) throw new ArgumentException(); for (int i = 0; i < str.Length; i += chunkLength) { if (chunkLength + i > str.Length) chunkLength = str.Length - i; yield return str.Substring(i, chunkLength); } } } I should give credit to this post https://stackoverflow.com/a/8944374/117995 by #oleksii for the SplitBy method.
Postfix Expression Calculator Validation
I need this code to be edited slightly using a loop to tell the user that their input was incorrect and then let them retry typing in a post fix expression? import java.util.Scanner; public class Calculator { public static void main(String[] args) { Scanner scan = new Scanner(System.in) ; System.out.println("Enter your two numbers and the operation with spaces between e.g 8 9 -"); String calculation=scan.nextLine(); String [] parts = calculation.split(" "); try{ double part1 = Double.parseDouble(parts[0]); double part2 = Double.parseDouble(parts[1]); double answer = 0; boolean incorrectOperation = false; String operation = parts[2]; switch (operation) { case "+": answer = part1 + part2; break; case "-": answer = part1 - part2; break; case "*": answer = part1 * part2; break; case "/": answer = part1 / part2; break; default: incorrectOperation = true; } String ans; if(incorrectOperation) { ans = "Please use +, -, * or / for operation"; } else { ans = String.valueOf(answer); } System.out.println(ans); } catch (NumberFormatException e) { System.out.println("Invalid expression " + calculation); } } } It needs to have some sort of message output using 'System.out.println' to tell the user what they have type is incorrect
How to get a substring in some length for special chars like Chinese
For example, I can get 80 chars with {description?substring(0, 80)} if description is in English, but for Chinese chars, I can get only about 10 chars, and there is a garbage char at the end always. How can I get 80 chars for any language?
FreeMarker relies on String#substring to do the actual (UTF-16-chars-based?) substring calculation, which doesn't work well with Chinese characters. Instead one should uses Unicode code points. Based on this post and FreeMarker's own substring builtin I hacked together a FreeMarker TemplateMethodModelEx implementation which operates on code points: public class CodePointSubstring implements TemplateMethodModelEx { #Override public Object exec(List args) throws TemplateModelException { int argCount = args.size(), left = 0, right = 0; String s = ""; if (argCount != 3) { throw new TemplateModelException( "Error: Expecting 1 string and 2 numerical arguments here"); } try { TemplateScalarModel tsm = (TemplateScalarModel) args.get(0); s = tsm.getAsString(); } catch (ClassCastException cce) { String mess = "Error: Expecting numerical argument here"; throw new TemplateModelException(mess); } try { TemplateNumberModel tnm = (TemplateNumberModel) args.get(1); left = tnm.getAsNumber().intValue(); tnm = (TemplateNumberModel) args.get(2); right = tnm.getAsNumber().intValue(); } catch (ClassCastException cce) { String mess = "Error: Expecting numerical argument here"; throw new TemplateModelException(mess); } return new SimpleScalar(getSubstring(s, left, right)); } private String getSubstring(String s, int start, int end) { int[] codePoints = new int[end - start]; int length = s.length(); int i = 0; for (int offset = 0; offset < length && i < codePoints.length;) { int codepoint = s.codePointAt(offset); if (offset >= start) { codePoints[i] = codepoint; i++; } offset += Character.charCount(codepoint); } return new String(codePoints, 0, i); } } You can put an instance of it into your data model root, e.g. SimpleHash root = new SimpleHash(); root.put("substring", new CodePointSubstring()); template.process(root, ...); and use the custom substring method in FTL: ${substring(description, 0, 80)} I tested it with non-Chinese characters, which still worked, but so far I haven't tried it with Chinese characters. Maybe you want to give it a try.
How do I retrieve global contacts with Exchange Web Services (EWS)?
I am using EWS and wish to obtain the global address list from exchange for the company. I know how to retrieve the personal contact list. All the samples in the API documentation deal with updating user information but not specifically how to retrieve them. I've even tried the following to list the folders but it doesn't yeild the correct results. private static void ListFolder(ExchangeService svc, FolderId parent, int depth) { string s; foreach (var v in svc.FindFolders(parent, new FolderView(int.MaxValue))) { Folder f = v as Folder; if (f != null) { s = String.Format("[{0}]", f.DisplayName); Console.WriteLine(s.PadLeft(s.Length + (depth * 2))); ListFolder(svc, f.Id, depth + 1); try { foreach (Item i in f.FindItems(new ItemView(20))) { Console.WriteLine( i.Subject.PadLeft(i.Subject.Length + ((depth + 1) * 2))); } } catch (Exception) { } } } } While the question has already been raised (How to get contact list from Exchange Server?) this question deals specifically with using EWS to get the global address list while this question asks for advice on a general level.
you may got ItemType objects in a specifiedfolder with the code snippet below and then cast ItemType objects to ContactItemType (for contact objects) .... /// <summary> /// gets list of ItemType objects with maxreturncriteria specicification /// </summary> /// <param name="esb">ExchangeServiceBinding object</param> /// <param name="folder">FolderIdType to get items inside</param> /// <param name="maxEntriesReturned">the max count of items to return</param> public static List<ItemType> FindItems(ExchangeServiceBinding esb, FolderIdType folder, int maxEntriesReturned) { List<ItemType> returnItems = new List<ItemType>(); // Form the FindItem request FindItemType request = new FindItemType(); request.Traversal = ItemQueryTraversalType.Shallow; request.ItemShape = new ItemResponseShapeType(); request.ItemShape.BaseShape = DefaultShapeNamesType.AllProperties; request.ParentFolderIds = new FolderIdType[] { folder }; IndexedPageViewType indexedPageView = new IndexedPageViewType(); indexedPageView.BasePoint = IndexBasePointType.Beginning; indexedPageView.Offset = 0; indexedPageView.MaxEntriesReturned = 100; indexedPageView.MaxEntriesReturnedSpecified = true; request.Item = indexedPageView; FindItemResponseType response = esb.FindItem(request); foreach (FindItemResponseMessageType firmtMessage in response.ResponseMessages.Items) { if (firmtMessage.ResponseClass == ResponseClassType.Success) { if (firmtMessage.RootFolder.TotalItemsInView > 0) foreach (ItemType item in ((ArrayOfRealItemsType)firmtMessage.RootFolder.Item).Items) returnItems.Add(item); //Console.WriteLine(item.GetType().Name + ": " + item.Subject + ", " + item.DateTimeReceived.Date.ToString("dd/MM/yyyy")); } else { //handle error log here } } return returnItems; }
I just did a similiar thing. However, I was unable to get the list of contacts via Exchange since that only gets users that have mailboxes, and not necessarily all users or groups. I eventually ended up getting all the users via AD here is code to get all the contacts in AD. All you need is the folderID of the global address list which can be gotten from using the ADSI.msc tool on your AD server and browsing to the Global address list folder, look at properties and grab the value of the "purported search". In my system the searchPath for the global address list is"(&(objectClass=user)(objectCategory=person)(mailNickname=)(msExchHomeServerName=))" public List<ListItem> SearchAD(string keyword, XmlDocument valueXml) { List<ListItem> ewsItems = new List<ListItem>(); using (DirectoryEntry ad = Utils.GetNewDirectoryEntry("LDAP://yourdomain.com")) { Trace.Info("searcherをつくる"); using (DirectorySearcher searcher = new DirectorySearcher(ad)) { if (this.EnableSizeLimit) { searcher.SizeLimit = GetMaxResultCount(); if (Utils.maxResultsCount > 1000) { searcher.PageSize = 100; } } else { searcher.SizeLimit = 1000; searcher.PageSize = 10; } string sisya = Utils.DecodeXml(valueXml.SelectSingleNode("Folder/SearchPath").InnerText); //this is the folder to grab your contacts from. In your case Global Address list //Container if(String.IsNullOrEmpty(sisya)) { return null; } keyword = Utils.EncodeLdap(keyword); string text = Utils.DecodeXml(valueXml.SelectSingleNode("Folder/Text").InnerText); searcher.Filter = this.CreateFilter(keyword, sisya); searcher.Sort = new SortOption("DisplayName", System.DirectoryServices.SortDirection.Ascending); //一つのPropertyをロードすると、全Propertyを取らないようになる searcher.PropertiesToLoad.Add("SAMAccountName"); //どのPropertyでもいい。 SearchResultCollection searchResults = searcher.FindAll(); foreach (SearchResult searchResult in searchResults) { //ListItem contact = null; using (DirectoryEntry userEntry = searchResult.GetDirectoryEntry()) { try { string schemaClassName = userEntry.SchemaClassName; switch (schemaClassName) { case "user": case "contact": string fname = userEntry.Properties["GivenName"].Value == null ? "" : userEntry.Properties["GivenName"].Value.ToString(); string lname = userEntry.Properties["sn"].Value == null ? "" : userEntry.Properties["sn"].Value.ToString(); string dname = userEntry.Properties["DisplayName"][0] == null ? lname + " " + fname : userEntry.Properties["DisplayName"][0].ToString(); //No Mail address if ((userEntry.Properties["mail"] != null) && (userEntry.Properties["mail"].Count > 0)) { string sAMAccountName = ""; if(userEntry.Properties["SAMAccountName"].Value != null){ sAMAccountName = userEntry.Properties["SAMAccountName"].Value.ToString(); } else{ sAMAccountName = userEntry.Properties["cn"].Value.ToString(); } string contactXml = Utils.ListViewXml(sAMAccountName, UserType.User, Utils.UserXml(fname, lname, userEntry.Properties["mail"].Value.ToString(), dname, null), ServerType.Ad); ewsItems.Add(new ListItem(dname + "<" + userEntry.Properties["mail"].Value.ToString() + ">", contactXml)); } else { ListItem contact = new ListItem(dname, null); contact.Enabled = false; ewsItems.Add(contact); Trace.Info("追加できないユーザ: " + searchResult.Path); } break; case "group": ewsItems.Add(new ListItem(userEntry.Properties["DisplayName"].Value.ToString(), Utils.ListViewXml(userEntry.Properties["SAMAccountName"].Value.ToString(), UserType.Group, null, ServerType.Ad))); break; default: userEntry.Properties["SAMAccountName"].Value.ToString()); ewsItems.Add(new ListItem(userEntry.Properties["name"].Value.ToString(), Utils.ListViewXml(userEntry.Properties["SAMAccountName"].Value.ToString(), UserType.Group, null, ServerType.Ad))); break; } } catch (Exception ex) { Trace.Error("User data取得失敗", ex); } } } searchResults.Dispose(); } } return ewsItems; }