【问题标题】:Java send email avoiding smtp relay server and send directly to MX serverJava发送电子邮件避免smtp中继服务器并直接发送到MX服务器
【发布时间】:2016-03-14 20:46:51
【问题描述】:

我正在尝试将电子邮件直接发送到目标 MX 服务器,避开中继 smtp 服务器。 从理论上讲,可以让名称服务器列表对 dns 服务器进行查询。 所以,使用这个类,http://www.eyeasme.com/Shayne/MAILHOSTS/mailHostsLookup.html,我可以得到一个域的邮件交换服务器的列表。

那么,一旦我有了这个,我该如何继续发送电子邮件?我应该使用 javax.mail 还是如何?如果是,我应该如何配置它?

【问题讨论】:

    标签: java email smtp jakarta-mail


    【解决方案1】:

    好的,假设我们这样做。

    我们进行 DNS 查找以获取收件人域的 MX 记录。下一步是连接到该服务器并传递消息。由于作为 MX 运行的主机必须侦听端口 25 并且需要接受未加密的通信,我们可以这样做:

    • 获取 MX 主机名
    • 创建Session 并将mail.smtp.host 设置为所述服务器
    • 发送邮件

    我们会得到什么?

    • 不再需要中继服务器。

    我们会失去什么?

    • 我们会变慢(DNS 查找,连接到世界各地的目标主机)
    • 我们将不得不进行完整错误处理(如果主机宕机了怎么办?我们什么时候重试?)
    • 我们将不得不通过垃圾邮件预防来做到这一点。因此,至少我们的服务器必须解析回我们发送电子邮件的域。

    结论:我不会那样做。有一些替代方案(安装本地 sendmail/postfix 等)完全能够为我们完成繁重的 SMTP 工作,同时仍然简化了我们需要在 Java 中完成的工作以让邮件正常发送。

    工作示例

    以下代码通过使用 gmail.com 的 DNS 解析 MX 条目向我发送电子邮件。猜猜发生了什么?被归类为垃圾邮件,因为谷歌说“它很可能不是从一月开始的”

    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;     
        }
    }
    

    【讨论】:

    • 很好的答案!只有一件事:在 message.setFrom("XXXXXXXXXXXXXXXXXXXXX@gmail.com"));必须是“新的 Internet 地址”??
    • 不适用于 JavaMail 1.5 - 他们将便利方法 setFrom(String from) 添加到 MimeMessage。但是是的 - 如果你想显示姓名和地址,那就是这样。
    • 我收到了这个异常:使用 zen.spamhaus.org 被阻止是因为我的 ip 现在在这个黑名单中吗?
    • 正如 Jan 所描述的,这比您想象的要困难得多。您认为通过避免中继 smtp 服务器可以获得什么?您认为这会带来更高的性能,让您更快地发送垃圾邮件吗?
    • @mig-foxbat 这将使使用这种直接方法更加难以实施。是的,您必须为每个域执行不同的会话 - 有 Transport.send 方法允许您指定发送到的地址
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-17
    • 2012-06-10
    • 2016-09-07
    • 1970-01-01
    相关资源
    最近更新 更多