IMPORTANT
I have been blocked by hotmail services. There is a control mechanism
called spamhaus which kicked me out. I'm stuck right now.
I am trying to detect an email address is valid and if its valid then check if this email address potentially used (I know that its not certain). For example, lets assume that there is a website with domain myimaginarydomain.com. If I run code below, I guess it won't fail because domain address is valid. But nobody can take an email address with that domain.
Is there any way to find out that email address is valid? (In this case its invalid)
I don't want to send confirmation email
Sending ping may be useful?
public class Application {
private static EmailValidator validator = EmailValidator.getInstance();
public static void main(String[] args) {
while (true) {
Scanner scn = new Scanner(System.in);
String email = scn.nextLine();
boolean isValid = validateEmail(email);
System.out.println("Syntax is : " + isValid);
if (isValid) {
String domain = email.split("#")[1];
try {
int test = doLookup(domain);
System.out.println(domain + " has " + test + " mail servers");
} catch (NamingException e) {
System.out.println(domain + " has 0 mail servers");
}
}
}
}
private static boolean validateEmail(String email) {
return validator.isValid(email);
}
static int doLookup(String hostName) throws NamingException {
Hashtable env = new Hashtable();
env.put("java.naming.factory.initial",
"com.sun.jndi.dns.DnsContextFactory");
DirContext ictx = new InitialDirContext(env);
Attributes attrs =
ictx.getAttributes(hostName, new String[]{"MX"});
Attribute attr = attrs.get("MX");
if (attr == null) return (0);
return (attr.size());
}
}
There is no failsafe way to do this in all cases, but, assuming the server uses SMTP then https://www.labnol.org/software/verify-email-address/18220/ gives quite a good tutorial on one method that may work.
The method used in the tutorial relies on OS tools, so you will need to ensure they exist before using them. a ProcessBuilder may help. Alternatively, you can open a socket directly in code and avoid using OS-dependent tools.
Essentially, you find out what the mail servers are (using nslookup), then telnet to one of the mail servers and start writing an email:
3a: Connect to the mail server:
telnet gmail-smtp-in.l.google.com 25
3b: Say hello to the other server
HELO
3c: Identify yourself with some fictitious email address
mail from:<labnol#labnol.org>
3d: Type the recipient’s email address that you are trying to verify:
rcpt to:<billgates#gmail.com>
The server response for rcpt to command will give you an idea whether an email address is valid or not. You’ll get an “OK” if the address exists else a 550 error
There really is no sensible way except trying to send a notification with a token to the address and ask the other party to confirm it, usually by visiting a web-page:
the recipients MX may be unavailable at the moment but come back online later, so you cannot rely on a lookup in real time;
just because the MX accepts the email doesn't mean that the address is valid, the message could bounce later down the pipe (think UUCP);
if this is some kind of registration service, you need to provide some confirmation step anyway as otherwise it'd become too easy to subscribe random strangers on the internet that do not want your service.
Related
I want to implement basic network check functionality to test if the provided url is responding or not (eg. ping www.google.com).It must provide operational information indicating, for example, that a requested service is not available or that a host could not be reached. I am able to achive it using icmp4j library. But i want to achieve the same using pcap4j library. I want to put the url in text box and click on connect button which will call pcap4j api to check whether the host is responding or not.
You can create ICMPv4 Echo (ping) on Ethernet packets using the Builders of IcmpV4EchoPacket, IcmpV4CommonPacket, IpV4Packet, and EthernetPacket and send them by PcapHandle.sendPacket(). Please refer to org.pcap4j.sample.SendFragmentedEcho in pcap4j-sample project.
You will need to implement ARP to resolve IP addresses to MAC addresses like org.pcap4j.sample.SendArpRequest in pcap4j-sample project.
And you will also need to implement a feature to find the next hop (default gateway or so) from the given IP address somehow. Pcap4J doesn't provide API to support this implementation. (Java doesn't provide API to get routing table...)
You'd maybe better use java.net.InetAddress#isReachable() instead.
It took me more than a year to figure this out, as I wanted to make a traceroute with pcap4j, so here is what I did:
Get your IPv4 Address and Mac Address, this can be easily achieved by querying the PcapNetworkInterface
Get target IP Address, if you have a DNS Name you need to resolve it beforehand.
Get target Mac Address.
Target is in the same subnet: send an ARP Request to resolve the mac (alternatively, a mac broadcast will likely work fine too).
Target is in different subnet: you need to get the mac of your gateway server then, this is not as easy. Assuming you have other network traffic going on, you could listen for incoming packets and get the source mac, where the source IP address is from a different subnet, this is likely the mac address of your gateway server.
Create IcmpV4EchoPacket and sent it
Listen for incoming ICMP traffic, you will get one of these three:
A IcmpV4EchoReplyPacket which is likely to be an answer to your request (check identifier and sequence number to be sure)
A IcmpV4TimeExceededPacket if the target could not be reached with the time-to-live you specified
Nothing, routers and pinged targets are free to ignore and not answer your request
Variables that need to be filled:
short IDENTIFIER; // identifer may be any 16 bit interger
short SEQUENCE; // sequence may be any 16 bit integer
byte TTL; // time to live (1-255)
Inet4Address IP_TARGET; // ip address of your ping target
Inet4Address IP_ORIGIN; // your own ip address
MacAddress MAC_TARGET; // target or gateway mac address
MacAddress MAC_SOURCE; // your own mac address
PcapNetworkInterface PCAP4J_NETWORK_INTERFACE; // network interface used to execute the ping
How to make a ICMP Echo Request Packet (as payload of IcmpV4CommonPacket of IpV4Packet of EthernetPacket):
public Packet buildPacket() {
IcmpV4EchoPacket.Builder icmpV4Echo = new IcmpV4EchoPacket.Builder()
.identifier(IDENTIFIER) // optional, default zero
.sequenceNumber(SEQUENCE); // optional, default zero
IcmpV4CommonPacket.Builder icmpV4Common = new IcmpV4CommonPacket.Builder()
.type(IcmpV4Type.ECHO) // type is echo
.code(IcmpV4Code.NO_CODE) // echo request doesn't need this
.payloadBuilder(icmpV4Echo)
.correctChecksumAtBuild(true);
IpV4Packet.Builder ipv4Builder = new IpV4Packet.Builder()
.correctChecksumAtBuild(true)
.correctLengthAtBuild(true)
.dstAddr(IP_TARGET) // IPv4 Address where tp send the request
.payloadBuilder(icmpV4Common)
.protocol(IpNumber.ICMPV4) // payload is ICMPV4
.srcAddr(IP_ORIGIN) // Your own IPv4 Address
.tos(IpV4Rfc1349Tos.newInstance((byte) 0))
.ttl(TTL) // time to live (1-255)
.version(IpVersion.IPV4); // IP Version is IPv4
EthernetPacket.Builder etherBuilder = new EthernetPacket.Builder()
.dstAddr(MAC_TARGET) // the targets mac address
.srcAddr(MAC_SOURCE) // your own mac address
.type(EtherType.IPV4) // payload protocl is IPv4
.payloadBuilder(ipv4Builder)
.paddingAtBuild(true);
return etherBuilder.build(); // build your packet
}
Listener for ICMP Echo Answers or timeouts:
public PacketListener buildListener() {
return new PacketListener() {
#Override
public void gotPacket(Packet packet) {
if (!(packet instanceof EthernetPacket))
return;
EthernetPacket ethernetPacket = (EthernetPacket) packet;
packet = ethernetPacket.getPayload();
if (!(packet instanceof IpV4Packet))
return;
IpV4Packet ipV4Packet = (IpV4Packet) packet;
IpV4Header ipV4Header = ipV4Packet.getHeader();
packet = ipV4Packet.getPayload();
if (!(packet instanceof IcmpV4CommonPacket))
return;
IcmpV4CommonPacket icmpPacket = (IcmpV4CommonPacket) packet;
packet = icmpPacket.getPayload();
// successful reply just measure time and done
if (packet instanceof IcmpV4EchoReplyPacket) {
IcmpV4EchoReplyPacket icmpV4EchoReplyPacket = (IcmpV4EchoReplyPacket) packet;
IcmpV4EchoReplyHeader icmpV4EchoReplyHeader = icmpV4EchoReplyPacket.getHeader();
if (icmpV4EchoReplyHeader.getIdentifier() != identifier)
return;
if (icmpV4EchoReplyHeader.getSequenceNumber() != sequence)
return;
// here you got an echo reply
System.out.println(packet);
return;
}
// try handle time to live exceeded messages
if (packet instanceof IcmpV4TimeExceededPacket) {
packet = packet.getPayload(); // original IPv4
if (!(packet instanceof IpV4Packet))
return;
packet = packet.getPayload(); // original ICMP common
if (!(packet instanceof IcmpV4CommonPacket))
return;
packet = packet.getPayload(); // original ICMP echo
if (!(packet instanceof IcmpV4EchoPacket))
return;
IcmpV4EchoHeader icmpV4EchoHeader = ((IcmpV4EchoPacket)packet).getHeader();
if (icmpV4EchoHeader.getIdentifier() != IDENTIFIER)
return;
if(icmpV4EchoHeader.getSequenceNumber() != SEQUENCE)
return;
// HERE you got an answer, that the time to live has been used up
System.out.println(packet);
return;
}
};
}
Combining it togther:
public static void main(String[] args) throws IOException, PcapNativeException, NotOpenException, InterruptedException {
try (PcapHandle handle = PCAP4J_NETWORK_INTERFACE.openLive(1024, PromiscuousMode.PROMISCUOUS, 1000)) {
// set filter to only get incoming ICMP traffic
handle.setFilter("icmp and dst host " + Pcaps.toBpfString(IP_ORIGIN), BpfCompileMode.OPTIMIZE);
// send ARP request
Packet p = buildPacket();
handle.sendPacket(p);
// wait (forever) for ARP answer
PacketListener listener = buildListener();
handle.loop(-1, listener);
}
}
Ok so the program is designed to take in connections, validate them, and resend that validation code. Before anyone get's angry it's just a simple little project and is not designed to be overly complex haha. However for some very strange reason the function is hanging on send.setAddess(packet.getAddress); I know this because I have commented out each individual line of code that deals with the Datagram packet "send" and have found that it "hangs" (or never progresses forward in the method again) on that particular line. Any thoughts? Am I doing something cluelessly wrong? I tried it on a linux server as well to make sure it didn't have anything to do with me and the same crap happened.
public static boolean authorize(String n, DatagramPacket packet) {
DatagramPacket send = new DatagramPacket(new byte[4096], 4096);
try {
System.out.println("in auth");
String[] t1 = n.split("%#");
String name = t1[1];
int k = genKey(name);
clients.put(name, k);
send.setAddress(packet.getAddress());
System.out.println("set add");
send.setPort(packet.getPort());
System.out.println("set port");
send.setData(("l-succeed%#" + Integer.toString(k)).getBytes());
System.out.println("set data");
main.dispathcer(send);
System.out.println("called send");
return true;
} catch(Exception e) {
send.setData("l-failed".getBytes());
main.dispathcer(send);
return false;
}
}
EDIT: it took 6 minutes before the authorization token was received by the client. So obviously the setAddress() works but is taking far too long...
It's possible that the process is hanging because there's an issue doing DNS resolution on the address for packet when you call .getAddress(). A few DNS calls are made in order to create the InetAddress object. On these machines, are you able to do a reverse DNS lookup on the IP that the packet packet came from? Try setting an entry for this IP in your /etc/hosts file.
I try to access email account on a certain email server via "imap" through java mail. I did some research on this. And I find the following code which works for gmail.
import java.io.*;
import javax.mail.*;
import javax.mail.internet.*;
public class DeleteMessageExample {
public static void main (String args[]) throws Exception {
String host = args[0];
String username = args[1];
String password = args[2];
// Get session
Session session = Session.getInstance(
System.getProperties(), null);
// Get the store
Store store = session.getStore("imaps");
store.connect(host, username, password);
// Get folder
Folder folder = store.getFolder("INBOX");
folder.open(Folder.READ_WRITE);
BufferedReader reader = new BufferedReader (
new InputStreamReader(System.in));
// Get directory
Message message[] = folder.getMessages();
for (int i=0, n=message.length; i<n; i++) {
System.out.println(i + ": " + message[i].getFrom()[0]
+ "\t" + message[i].getSubject());
System.out.println("Do you want to delete message? [YES to delete]");
String line = reader.readLine();
// Mark as deleted if appropriate
if ("YES".equals(line)) {
message[i].setFlag(Flags.Flag.DELETED, true);
}
}
// Close connection
folder.close(true);
store.close();
}
}
However, I need to specify the args[0] to be imap.gmail.com args[1] to be usrname, args[2] to be password. And if I replace imap.gmail.com by the ip address 74.125.224.86, it no longer work.
My question is suppose I have an account on yahoo mail, what the hostname I should use?
I tried imap.yahoo.com, mail.yahoo.com and the ip address.
If you know the answer, would you mind also told me what is the regular rule to find out what kind hostname I should use?
Thanks a lot.
Unlike Gmail, Yahoo Mail's IMAP services is not a totally standard IMAP service. You need send some special tokens before you login. You need to modify the JavaMail API in order to connect to Yahoo Mail through IMAP. The latest JavaMail 1.4.4-SNAPSHOT release supports Yahoo Mail as well. You can get it here
I would like to implement a 'Send Feedback' option in a Java desktop application. One which will pop up a box for the user to enter a comment, then send it to us along with a screenshot of the application window.
How would be the best way to communicate the data to us? Two obvious solutions spring to mind:
Email - I'm thinking that the application would connect to an SMTP server set-up by us, with the username/password somehow hidden in the code. SMTP over SSL for security (not of the data being sent, but of the SMTP username/password).
Web service - pretty self explanatory.
Which of these would be best, or is there a better alternative?
A webserivce would be far better, since the connection to an SMTP server might be blocked.
Another idea would be to use Google Docs. This would be like the website idea but you wouldnt need to set any server-side stuff yourself. You could create a Google Docs spreadsheet with the fields you will be collecting, then have your Java app write the submission to the spreadhseet using the google docs API. Then add a notification to the spreadsheet to automatically send you an email when a new row is written.
A web service sounds more reliable and less clumsy.
Client generally may make HTTP connections without firewall issues.
Much easier to setup, maintain and process HTTP server and requests.
As others mention, firewalls are an issue with SMTP. Still, there is a simple way to deliver mails without hosting your own infrastructure or "hidden" passwords. You could simply register a free mail account, e.g. gmail, and send mails directly to this address. As you aren't using Gmail's SMTP server as a relay, there is no need for username and password.
public static String[] lookupMailHosts(final String domainName) throws NamingException {
final InitialDirContext iDirC = new InitialDirContext();
final Attributes attributes = iDirC
.getAttributes("dns:/" + domainName, new String[] { "MX" });
final Attribute attributeMX = attributes.get("MX");
if (attributeMX == null) {
return new String[] { domainName };
}
final String[][] pvhn = new String[attributeMX.size()][2];
for (int i = 0; i < attributeMX.size(); i++) {
pvhn[i] = ("" + attributeMX.get(i)).split("\\s+");
}
// sort the MX RRs by RR value (lower is preferred)
Arrays.sort(pvhn, new Comparator<String[]>() {
public int compare(final String[] o1, final String[] o2) {
return Integer.parseInt(o1[0]) - Integer.parseInt(o2[0]);
}
});
// put sorted host names in an array, get rid of any trailing '.'
final String[] sortedHostNames = new String[pvhn.length];
for (int i = 0; i < pvhn.length; i++) {
sortedHostNames[i] = pvhn[i][1].endsWith(".") ? pvhn[i][1].substring(0, pvhn[i][1]
.length() - 1) : pvhn[i][1];
}
return sortedHostNames;
}
for example:
public static void main(String[] args) throws Exception {
// prints [gmail-smtp-in.l.google.com, alt1.gmail-smtp-in.l.google.com, alt2.gmail-smtp-in.l.google.com, alt3.gmail-smtp-in.l.google.com, alt4.gmail-smtp-in.l.google.com]
System.out.println(Arrays.asList(lookupMailHosts("gmail.com")));
}
so you would use "gmail-smtp-in.l.google.com" as your first choice for javax.mail:
Properties props = new Properties();
props.setProperty("mail.smtp.host", lookupMailHosts("gmail.com")[0]);
// ... other properies
Session smtpSession = Session.getInstance(props, null)
You could even combine this approach with a simple HTTP to SMTP kind of service hosted on AppEngine. All it would have to do is receive HTTP POST requests and forward them as an email using the method shown above.
I'd like to send mail without bothering with the SMTP-Server which is used for delivery.
So JavaMail API doesn't work for me because I have to specify a SMTP server to connect to.
I'd like the library to find out on its own which SMTP server is responsible for which email address by querying the MX record of the mail address domain.
I'm looking for something like Aspirin. Unfortunately I can't use Aspirin itself because the development stopped 2004 and the library fails to communicate with modern spam hardened servers correctly.
An embeddable version of James would do the task. But I haven't found documentation concerning whether this is possible.
Or does anyone know about other libraries I could use?
One possible solution: get the MX record on your own and use JavaMail API.
You can get the MX record using the dnsjava project:
Maven2 dependency:
<dependency>
<groupId>dnsjava</groupId>
<artifactId>dnsjava</artifactId>
<version>2.0.1</version>
</dependency>
Method for MX record retrieval:
public static String getMXRecordsForEmailAddress(String eMailAddress) {
String returnValue = null;
try {
String hostName = getHostNameFromEmailAddress(eMailAddress);
Record[] records = new Lookup(hostName, Type.MX).run();
if (records == null) { throw new RuntimeException("No MX records found for domain " + hostName + "."); }
if (log.isTraceEnabled()) {
// log found entries for debugging purposes
for (int i = 0; i < records.length; i++) {
MXRecord mx = (MXRecord) records[i];
String targetString = mx.getTarget().toString();
log.trace("MX-Record for '" + hostName + "':" + targetString);
}
}
// return first entry (not the best solution)
if (records.length > 0) {
MXRecord mx = (MXRecord) records[0];
returnValue = mx.getTarget().toString();
}
} catch (TextParseException e) {
throw new RuntimeException(e);
}
if (log.isTraceEnabled()) {
log.trace("Using: " + returnValue);
}
return returnValue;
}
private static String getHostNameFromEmailAddress(String mailAddress) throws TextParseException {
String parts[] = mailAddress.split("#");
if (parts.length != 2) throw new TextParseException("Cannot parse E-Mail-Address: '" + mailAddress + "'");
return parts[1];
}
Sending mail via JavaMail code:
public static void sendMail(String toAddress, String fromAddress, String subject, String body) throws AddressException, MessagingException {
String smtpServer = getMXRecordsForEmailAddress(toAddress);
// create session
Properties props = new Properties();
props.put("mail.smtp.host", smtpServer);
Session session = Session.getDefaultInstance(props);
// create message
Message msg = new MimeMessage(session);
msg.setFrom(new InternetAddress(fromAddress));
msg.setRecipient(Message.RecipientType.TO, new InternetAddress(toAddress));
msg.setSubject(subject);
msg.setText(body);
// send message
Transport.send(msg);
}
This is completely the wrong way to handle this.
Anyone connected to the internet will have some kind of "legit" SMTP server available to them to take the submission of email -- your ISP, your office, etc.
You WANT to leverage because they do several things for you.
1) they take your message and the responsibility to handle that message. After you drop it off, it's not your problem anymore.
2) Any mail de-spamming technologies are handled by the server. Even better, when/if those technologies change (Domain keys anyone?), the server handles it, not your code.
3) You, as a client of that sending mail system, already have whatever credentials you need to talk to that server. Main SMTP servers are locked down via authentication, IP range, etc.
4) You're not reinventing the wheel. Leverage the infrastructure you have. Are you writing an application or a mail server? Setting up mail server is an every day task that is typically simple to do. All of those casual "dumb" users on the internet have managed to get email set up.
Don't.
Sending email is much more complex than it seems. Email servers excel at (or should excel at) reliable delivery.
Set up a separate email server if you need to- that will be essentially the same as implementing one in Java (I doubt you will find libraries for this task- they would be essentially complete mail servers), but much more simpler.