
特點:發件方 MTA 負責重試、緩存、失敗通知;應用層難以即時感知投遞結果。

應用直接連接收件方 MX 記錄指向的 SMTP 伺服器 (端口 25) 發送郵件。
優勢:即時獲取投遞狀態(如地址不存在即時報錯),適合業務需即時感知的場景。
挑戰:需自行解析 MX 記錄、處理重試邏輯、應對反垃圾策略。
public class JavaMailSendingHandler implements ILocalEmailSendingHandler {
public void send(String to, String from, String subject, String content, String contentType) throws Exception {
Properties props = new Properties();
props.put("mail.smtp.localhost", getHost(from));
// 關鍵:動態解析收件域 MX 記錄
String smtpHost = getSMTPServerByJNDI(getHost(to));
props.setProperty("mail.smtp.host", smtpHost);
Session session = Session.getInstance(props, null);
MimeMessage message = new MimeMessage(session);
message.setContent(content, contentType);
message.setSender(new InternetAddress(from));
message.setFrom(new InternetAddress(from));
message.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
message.setSubject(subject);
// 設置標準郵件頭,提升信譽
message.setHeader("Content-Type", contentType);
message.setHeader("Content-Transfer-Encoding", "7bit");
message.setHeader("Date", new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z").format(new Date()));
Transport.send(message, new Address[]{new InternetAddress(to)});
}
private String getHost(String address) {
return address.substring(address.indexOf('@') + 1);
}
/** 透過 JNDI DNS 服務提供者查詢 MX 記錄 */
private String getSMTPServerByJNDI(String domain) throws Exception {
Properties env = new Properties();
env.put("java.naming.factory.initial", "com.sun.jndi.dns.DirContextFactory");
DirContext ctx = new InitialDirContext(env);
Attributes attrs = ctx.getAttributes(domain, new String[]{"MX"});
Attribute mxAttr = attrs.get("MX");
// 取優先級最高 (數值最小) 的 MX 記錄
String[] servers = new String[mxAttr.size()];
for (int i = 0; i < mxAttr.size(); i++) {
servers[i] = mxAttr.get(i).toString(); // 格式: "priority mail.example.com."
}
// 簡單取第一條,生產環境應按 priority 排序
String server = servers[0].split(" ")[1];
return server.endsWith(".") ? server.substring(0, server.length()-1) : server;
}
}

; 允許 192.168.1.0/24 網段及 mx.domain1.com 發送郵件,其餘拒絕
v=spf1 ip4:192.168.1.0/24 mx -all
關鍵機制:+all (通過)、-all (拒絕)、~all (軟失敗)、?all (中性)。