Java send email avoiding smtp relay server and send directly to MX server

坚强是说给别人听的谎言 提交于 2019-12-07 18:00:34

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:

  • get MX host name
  • create Session with mail.smtp.host set to said server
  • send mail

What would we gain?

  • No more need for relay server.

What would we lose?

  • We will be slower (DNS-Lookup, connections to target host around the world)
  • We will have to do full error-handling (What if host is down? When do we retry?)
  • We will have to make it through spam prevention. So at the very least our server has to resolve back to the domain we send our emails from.

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("XXXXXXXXXXXXXXXXXXXX@gmail.com");
            message.addRecipient(RecipientType.TO, new InternetAddress("XXXXXXXXXXXXXXXXXXXX@gmail.com"));
            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;     
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!