I'm trying to send an email directly to the destination MX server, avoiding the relay smtp server. Teorically it could be possible getting the name servers list doing a query to a dns server. So, using this class, http://www.eyeasme.com/Shayne/MAILHOSTS/mailHostsLookup.html , I can get a list of the mail exchange servers of a domain.
So, once I have that, how can I proceed to send the email? I should use javax.mail or how? And if is it, how I should configure it?
Okay, so suppose we do that.
We do DNS-Lookup to fetch MX records for recipient domain. Next step would be to connect to that server and deliver the message. As hosts operating as MX have to listen on port 25 and need to accept unencrypted communication, we could do it like that:
Session
with mail.smtp.host
set to said serverWhat would we gain?
What would we lose?
Conclusion: I woudn't do that. There are alternatives (install local sendmail/postfix whatever) that are perfectly able to do the hard SMTP work for us while still simplifying the work we need to do in Java to get the mail on its way.
Working example
Here's code that worked in sending me an email by using DNS resolved MX entry for gmail.com. Guess what happend? Got classified as SPAM because google said "it's most likely not from Jan"
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.mail.internet.MimeMessage.RecipientType;
import javax.naming.*;
import javax.naming.directory.*;
public class DirectMail {
public static void main(String[] args) {
try {
String[] mx = getMX("gmail.com");
for(String mxx : mx) {
System.out.println("MX: " + mxx);
}
Properties props = new Properties();
props.setProperty("mail.smtp.host", mx[0]);
props.setProperty("mail.debug", "true");
Session session = Session.getInstance(props);
MimeMessage message = new MimeMessage(session);
message.setFrom("[email protected]");
message.addRecipient(RecipientType.TO, new InternetAddress("[email protected]"));
message.setSubject("SMTP Test");
message.setText("Hi Jan");
Transport.send(message);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String[] getMX(String domainName) throws NamingException {
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
env.put(Context.PROVIDER_URL, "dns:");
DirContext ctx = new InitialDirContext(env);
Attributes attribute = ctx.getAttributes(domainName, new String[] {"MX"});
Attribute attributeMX = attribute.get("MX");
// if there are no MX RRs then default to domainName (see: RFC 974)
if (attributeMX == null) {
return (new String[] {domainName});
}
// split MX RRs into Preference Values(pvhn[0]) and Host Names(pvhn[1])
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, (o1, o2) -> Integer.parseInt(o1[0]) - Integer.parseInt(o2[0]));
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;
}
}