一JavaMail与SMTP
通常我们使用JavaMail都是通过SMTP服务器来发送邮件比如说我有一个的邮件账号想给的邮箱发送邮件
用户A首先将需要发送的邮件通过SMTP协议发送给他所在的邮件服务器domain然后domain判断收件人所在的域为domain于是domain通过SMTP协议再重新将邮件发送到domain最后用户B连接到自己的邮件服务器domain接收邮件通常domain会将邮件缓存以便出错时重新发送如果重试几次后还是发送失败可能会给用户A发送一封邮件以告知邮件发送失败如果用户A是一个应用的话很难知道邮件发送成功与否
另外一种做法是用户(或者我们自己的应用)直接连接对方的SMTP服务器来发送邮件其实就是连接到对方的端口然后按顺序发送一些SMTP的命令详细的SMTP信息大家可以查阅相应资料JavaMail对这些底层的数据传输做了很好的包装
只要用户A发送的数据格式和前面domain发送的相同对于domain来说没什么区别而且在这种方式下如果邮件发送失败比如收件人地址不存在用户A会马上得到邮件发送失败信息所以在实际的应用中这种方式比较常见但是这种方式需要知道对方的SMTP服务器的地址在Windows下可以在命令行执行nslookup输入 set type=mx然后输入需要查找的域名比如就可以查找到它的SMTP服务器地址同样在Java中可以通过JNDI或者开源的dnsjava查找收件人所在域的SMTP服务器地址这里给出一个简单的例子
public class JavaMailSendingHandler implements ILocalEmailSendingHandler {
public void send(String to String from String subject String content String contentType) throws Exception {
Properties props = new Properties();
propsput(mailsmtplocalhost getHost(from));
String server = getSMTPServerByJNDI(getHost(to));
propssetProperty(mailsmtphost server);
Session session = SessiongetInstance(props null);
MimeMessage message = new MimeMessage(session);
messagesetContent(content contentType);
messagesetSender(new InternetAddress(from));
messagesetFrom(new InternetAddress(from));
messagesetRecipient(RecipientTypeTO new InternetAddress(to));
messagesetSubject(subject);
messagesetHeader(ContentType contentType);
messagesetHeader(ContentTransferEncoding bit);
SimpleDateFormat format = new SimpleDateFormat(EEE d MMM yyyy HH:mm:ss Z);
messagesetHeader(Date formatformat(new Date()));
Transportsend(message new Address[] { new InternetAddress(to) });
}
private String getHost(String address) {
return addresssubstringaddressindexOf(@) + );
}
//通过JNDI 查找给定域的邮件服务器
private String getSMTPServerByJNDI(String host) throws Exception {
Properties jndiEnvironmentProperties = new Properties();
jndiEnvironmentPropertiesput(javanamingfactoryinitial comsunjndidnsDnsContextFactory);
DirContext initialDirContext = new InitialDirContext(jndiEnvironmentProperties);
Attributes attributes = initialDirContextgetAttributes(host new String[] {MX});
Attribute attribute = attributesget(MX);
String[] servers = new String[attributesize()];
for (int i = ; i < attributesize(); i++) {
servers[i] = attributeget(i)toString();
}
String server = servers[];
server = serversubstring(serverindexOf( ) + servers[]length() );
return server;
}
}
二反垃圾邮件机制
最简单的反垃圾邮件机制就是检查邮件的每个头信息是否短缺格式是否正确另外比较复杂的一种是SPF(Sender Policy Framework)它主要用来防止伪造的邮件地址还是采用前面的例子说明在用户直接给domain发送邮件时需要告示邮件发送者地址这样domain会根据邮件发送者的地址所在的域名查找到该域的有效的邮件服务器地址如果用户所在的计算机不再查找的结果之中那就说明发件人地址是伪造的从而断定是垃圾邮件
为了能够通过收件人邮件服务器的SPF检查需要向所在域的域控制器添加相应的SPF信息在Windows服务器下可以通过添加TXT记录来完成