Java отправляет электронную почту, избегая SMTP-сервера ретрансляции и отправляет непосредственно на сервер MX

Я пытаюсь отправить электронное письмо непосредственно на целевой сервер MX, избегая SMTP-сервера ретрансляции. Теоретически возможно получить список серверов имен, выполнив запрос к DNS-серверу. Итак, используя этот класс, http://www.eyeasme.com/Shayne/MAILHOSTS/mailHostsLookup.html, я могу получить список серверов обмена почтой домена.

Итак, когда у меня есть это, как я могу приступить к отправке электронного письма? Я должен использовать javax.mail или как? И если это, как я должен настроить это?

1 ответ

Решение

Итак, предположим, что мы делаем это.

Мы делаем DNS-Lookup, чтобы получить записи MX для домена получателя. Следующим шагом будет подключение к этому серверу и доставка сообщения. Поскольку хосты, работающие под управлением MX, должны прослушивать порт 25 и принимать незашифрованные сообщения, мы можем сделать это следующим образом:

  • получить имя хоста MX
  • Создайте Session с mail.smtp.host установить на указанный сервер
  • Отправить письмо

Что бы мы получили?

  • Больше нет необходимости в ретрансляционном сервере.

Что бы мы потеряли?

  • Мы будем медленнее (DNS-Lookup, соединения с целевым хостом по всему миру)
  • Мы должны будем выполнить полную обработку ошибок (Что, если хост не работает? Когда мы повторим попытку?)
  • Мы должны сделать это путем предотвращения спама. Так что, по крайней мере, наш сервер должен вернуться к домену, с которого мы отправляем наши электронные письма.

Вывод: я не буду этого делать. Существуют альтернативы (устанавливайте локальный sendmail/postfix независимо от того, что именно), которые прекрасно могут выполнить тяжелую работу SMTP за нас, в то же время упрощая работу, которую мы должны сделать в Java, чтобы получать почту в пути.

Рабочий пример

Вот код, который работал при отправке мне электронного письма с использованием DNS-записи MX для gmail.com. Угадай, что случилось? Был классифицирован как СПАМ, потому что Google сказал: "Скорее всего, не с января"

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;     
    }
}
Другие вопросы по тегам