基于james實(shí)現(xiàn)在物理隔離環(huán)境下郵件的傳輸
背景
為了保護(hù)高安全級(jí)別的網(wǎng)絡(luò)安全,國(guó)家保密局于1999年12月27日發(fā)布了涉密網(wǎng)絡(luò)的物理隔離要求,并于2000年1月1日頒布實(shí)施的《計(jì)算機(jī)信息系統(tǒng)國(guó)際聯(lián)網(wǎng)保密管理規(guī)定》,該規(guī)定中第二章保密制度第六條規(guī)定;“涉及國(guó)家秘密的計(jì)算機(jī)信息系統(tǒng),不得直接或間接地與國(guó)際互聯(lián)網(wǎng)或其他公共信息網(wǎng)絡(luò)相連接,必須實(shí)行物理隔離把曼〗低”
物理隔離通常是通過(guò)部署網(wǎng)閘來(lái)切斷內(nèi)網(wǎng)和外網(wǎng)的物理連接和邏輯連接黎烈,網(wǎng)閘只擺渡原始數(shù)據(jù)旭绒,而不容許任何連接或者協(xié)議經(jīng)過(guò)網(wǎng)閘俱箱。在這種環(huán)境下寇壳,內(nèi)外網(wǎng)郵件的傳輸成了難題日丹。本文以探究的方式嘗試提供一套思路和實(shí)現(xiàn)解決該場(chǎng)景下的郵件傳輸贰您,本文包含的代碼都是demo級(jí)別代碼鲤桥,秉著對(duì)新領(lǐng)域的探究揍拆,但不確定該方法是不是合適該場(chǎng)景的解決方案。
環(huán)境與配置
本文采用的環(huán)境如下:
pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>MailInPIE</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.8</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.rocketmq</groupId>
<artifactId>rocketmq-client</artifactId>
<version>4.2.0</version>
</dependency>
</dependencies>
</project>
架構(gòu)思路
大致的架構(gòu)如下圖:
- mailet程序片段主要包含DivestitureAgreementMatcher和DivestitureAgreementMailet兩個(gè)程序茶凳,DivestitureAgreementMatcher主要用于匹配內(nèi)外網(wǎng)用戶,如果是內(nèi)網(wǎng)用戶則放行贮喧,如果是外網(wǎng)用戶筒狠,則將該郵件交給DivestitureAgreementMailet進(jìn)行處理;DivestitureAgreementMailet將郵件的原始內(nèi)容抽出箱沦,必要時(shí)可對(duì)原始內(nèi)容進(jìn)行切割辩恼,發(fā)送到消息隊(duì)列。
- 消息隊(duì)列主要存儲(chǔ)將要擺渡的消息谓形,將內(nèi)部的消息經(jīng)由消息API取出运挫,交給網(wǎng)閘進(jìn)行擺渡
- 網(wǎng)閘負(fù)責(zé)消息的擺渡,本質(zhì)是對(duì)一塊共享內(nèi)存的分時(shí)讀寫實(shí)現(xiàn)內(nèi)外網(wǎng)在物理隔離和邏輯隔離環(huán)境下的數(shù)據(jù)傳輸
- 網(wǎng)閘另一端的消息API將網(wǎng)閘擺渡過(guò)來(lái)的內(nèi)網(wǎng)消息發(fā)送給消息隊(duì)列
- 郵件轉(zhuǎn)發(fā)程序從消息隊(duì)列中取出待轉(zhuǎn)發(fā)的消息套耕,必要時(shí)重組消息谁帕,并進(jìn)行轉(zhuǎn)發(fā)。
由于重重困難冯袍,所以這個(gè)demo將跳過(guò)網(wǎng)閘部分匈挖,消息發(fā)送到消息隊(duì)列之后,消費(fèi)者直接將消息進(jìn)行轉(zhuǎn)發(fā)康愤,雖然沒(méi)有實(shí)際在網(wǎng)閘和內(nèi)外網(wǎng)的環(huán)境下測(cè)試儡循,但是!我覺得是可行的征冷!
代碼實(shí)現(xiàn)
mailet程序片段
mailet程序片段的實(shí)現(xiàn)思路如下:
DivestitureAgreementMatcher參考代碼:
package com.xxxxx.pie.mail.matcher;
import com.jlszkxa.pie.mail.db.DbOperation;
import org.apache.mailet.GenericRecipientMatcher;
import org.apache.mailet.MailAddress;
import java.sql.SQLException;
/**
* @ClassName DivestitureAgreementMatcher
* @Description 判斷接收人是否是內(nèi)網(wǎng)用戶择膝,是則匹配給Mailet進(jìn)行原始內(nèi)容抽取,否則放行
* @Author chenwj
* @Date 2020/2/20 14:53
* @Version 1.0
**/
public class DivestitureAgreementMatcher extends GenericRecipientMatcher {
@Override
public boolean matchRecipient(MailAddress mailAddress) {
DbOperation dbOperation = new DbOperation();
try {
dbOperation.connectDatabase();
String userName = mailAddress.getUser();
String host = mailAddress.getHost();
System.out.printf("截取到到發(fā)送給%s@%s的郵件\r\n", userName, host);
return !dbOperation.isInnerUser(userName + "@" + host);
} catch (Exception e) {
System.out.printf("發(fā)生異常 異常信息: %s\r\n", e.getMessage());
e.printStackTrace();
return true;
} finally {
try {
dbOperation.closeConnection();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
dbOperation參考代碼:
package com.xxxxxx.pie.mail.db;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.sql.*;
/**
* @ClassName DbOperation
* @Description 數(shù)據(jù)庫(kù)操作
* @Author chenwj
* @Date 2020/2/20 17:34
* @Version 1.0
**/
public class DbOperation {
private static final Logger logger = LoggerFactory.getLogger(DbOperation.class);
private Connection connection;
/*
連接數(shù)據(jù)庫(kù)
*/
public void connectDatabase() {
String driver = "com.mysql.jdbc.Driver";
String url = "jdbc:mysql://localhost:3306/mail?characterEncoding=UTF-8";
String userName = "root";
String password = "123456";
logger.info("開始連接數(shù)據(jù)庫(kù)");
try {
Class.forName(driver);
connection = DriverManager.getConnection(url, userName, password);
logger.info("數(shù)據(jù)庫(kù)連接成功");
} catch (Exception e) {
logger.warn("數(shù)據(jù)庫(kù)連接出現(xiàn)異常 異常信息: {}", e.getMessage());
}
}
/**
* 判斷該用戶是否為內(nèi)網(wǎng)用戶
*
* @param userName
* @return
* @throws Exception
*/
public boolean isInnerUser(String userName) throws Exception {
String sql = "select USER_NAME from james_user where USER_NAME = \'" + userName + "\';";
PreparedStatement pstmt = connection.prepareStatement(sql);
ResultSet rs = pstmt.executeQuery();
try {
if (rs.next()) {
return true;
}
return false;
} finally {
rs.close();
pstmt.close();
}
}
/*
關(guān)閉連接
*/
public void closeConnection() throws SQLException {
if (null != connection) {
connection.close();
}
}
public static void main(String[] args) throws Exception {
DbOperation test = new DbOperation();
test.connectDatabase();
boolean innerUser = test.isInnerUser("97983398@qq.com");
System.out.printf("結(jié)果為: %s\r\n", "true");
test.closeConnection();
}
}
本例中搭建的james郵件服務(wù)器將用戶信息存儲(chǔ)在數(shù)據(jù)庫(kù)中检激,因此可以直接通過(guò)查詢數(shù)據(jù)庫(kù)的手段判斷是否是內(nèi)網(wǎng)用戶肴捉。此外,也可以直接截取域名進(jìn)行判斷叔收。
DivestitureAgreementMailet參考代碼:
package com.xxxxxx.pie.mail.mailet;
import com.alibaba.fastjson.JSONObject;
import com.jlszkxa.pie.mail.entity.ForwardMail;
import org.apache.mailet.GenericMailet;
import org.apache.mailet.Mail;
import org.apache.rocketmq.client.exception.MQBrokerException;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.remoting.exception.RemotingException;
import javax.mail.MessagingException;
import java.io.IOException;
/**
* @author chenwj
* @version 1.0
* @className DivestitureAgreementMailet
* @description 截取郵件齿穗,剝離協(xié)議,并放入隊(duì)列等待網(wǎng)閘擺渡
* @date 2020/2/20 14:53
**/
public class DivestitureAgreementMailet extends GenericMailet {
@Override
public void service(Mail mail) throws MessagingException {
String sender = mail.getSender().toString();
String name = mail.getName();
String subject = mail.getMessage().getSubject();
String content = null;
try {
content = (String) mail.getMessage().getContent();
} catch (IOException e) {
e.printStackTrace();
}
System.out.printf("截取到%s的郵件 name:%s subject:%s content:%s\r\n", sender, name, subject, content);
System.out.println("將截取郵件發(fā)送到消息隊(duì)列中...");
DefaultMQProducer producer = new DefaultMQProducer("DivestitureAgreementGroup");
producer.setNamesrvAddr("localhost:9876");
producer.setInstanceName("rmq-instance");
try {
producer.start();
System.out.println("開啟消息隊(duì)列");
} catch (MQClientException e) {
e.printStackTrace();
}
try {
ForwardMail forwardMail = ForwardMail.newBuilder()
.content(mail.getMessage().getContent())
.from(mail.getSender().getUser() + "@" + mail.getSender().getHost())
.hostName(mail.getRemoteHost())
.recipients(mail.getRecipients().iterator().next())
.subject(mail.getMessage().getSubject())
.build();
Message message = new Message("demo-topic", "demo-tag", JSONObject.toJSONString(forwardMail).getBytes("UTF-8"));
producer.send(message);
System.out.println("消息成功轉(zhuǎn)發(fā)到消息隊(duì)列中");
System.out.printf("轉(zhuǎn)發(fā)內(nèi)容如下: %s\r\n", JSONObject.toJSONString(forwardMail));
} catch (MQClientException e) {
e.printStackTrace();
} catch (RemotingException e) {
e.printStackTrace();
} catch (MQBrokerException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally{
producer.shutdown();
System.out.println("關(guān)閉消息隊(duì)列");
}
}
}
ForwardMail對(duì)象如下:
package com.xxxxxx.pie.mail.entity;
/**
* @ClassName Mail
* @Description TODO
* @Author chenwj
* @Date 2020/2/21 13:42
* @Version 1.0
**/
public class ForwardMail {
private String hostName;
private String from;
private String subject;
private Object recipients;
private Object content;
public ForwardMail() {
}
private ForwardMail(Builder builder) {
setHostName(builder.hostName);
setFrom(builder.from);
setSubject(builder.subject);
setRecipients(builder.recipients);
setContent(builder.content);
}
public static Builder newBuilder() {
return new Builder();
}
public String getHostName() {
return hostName;
}
public void setHostName(String hostName) {
this.hostName = hostName;
}
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public Object getRecipients() {
return recipients;
}
public void setRecipients(Object recipients) {
this.recipients = recipients;
}
public Object getContent() {
return content;
}
public void setContent(Object content) {
this.content = content;
}
public static final class Builder {
private String hostName;
private String from;
private String subject;
private Object recipients;
private Object content;
private Builder() {
}
public Builder hostName(String val) {
hostName = val;
return this;
}
public Builder from(String val) {
from = val;
return this;
}
public Builder subject(String val) {
subject = val;
return this;
}
public Builder recipients(Object val) {
recipients = val;
return this;
}
public Builder content(Object val) {
content = val;
return this;
}
public ForwardMail build() {
return new ForwardMail(this);
}
}
}
將上述的mailet程序片段打成jar包饺律,粘貼復(fù)制到j(luò)ames服務(wù)器下..\james-2.3.2.1\apps\james\SAR-INF\lib
,如果SAR-INF目錄下沒(méi)有l(wèi)ib目錄窃页,則手動(dòng)新增該目錄,在..\james-2.3.2.1\apps\james\SAR-INF\config.xml
中增加如下配置:
重啟james服務(wù)器,mailet程序片段就可以生效了脖卖。下面是消費(fèi)端消息的轉(zhuǎn)發(fā)乒省。
郵件轉(zhuǎn)發(fā)程序
郵件的轉(zhuǎn)發(fā)其實(shí)是我考慮比較久的,內(nèi)網(wǎng)與外網(wǎng)無(wú)法建立連接的情況下畦木,要將消息原封不動(dòng)地進(jìn)行轉(zhuǎn)發(fā)作儿,且消息發(fā)送人依舊標(biāo)識(shí)是內(nèi)網(wǎng)的用戶,這是我期望實(shí)現(xiàn)的馋劈,但是我沒(méi)有找到好的解決辦法。我嘗試將郵件的from設(shè)置為內(nèi)網(wǎng)用戶晾嘶,或者將displayname設(shè)置為內(nèi)網(wǎng)用戶妓雾,在QQ郵箱中似乎都沒(méi)有得到比較好的結(jié)果。因此最后我取巧實(shí)現(xiàn)垒迂,在外網(wǎng)統(tǒng)一由一個(gè)外網(wǎng)用戶進(jìn)行轉(zhuǎn)發(fā)械姻,轉(zhuǎn)發(fā)時(shí)在subject中標(biāo)識(shí)該郵件轉(zhuǎn)發(fā)自內(nèi)網(wǎng)的某個(gè)用戶。
Consumer參考代碼:
package com.xxxxxx.pie.mail.mq;
import com.alibaba.fastjson.JSONObject;
import com.jlszkxa.pie.mail.entity.ForwardMail;
import com.jlszkxa.pie.mail.mail.MailSender;
import org.apache.rocketmq.client.consumer.DefaultMQPushConsumer;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext;
import org.apache.rocketmq.client.consumer.listener.ConsumeConcurrentlyStatus;
import org.apache.rocketmq.client.consumer.listener.MessageListenerConcurrently;
import org.apache.rocketmq.client.exception.MQClientException;
import org.apache.rocketmq.common.message.MessageExt;
import javax.mail.MessagingException;
import java.io.UnsupportedEncodingException;
import java.util.List;
public class Consumer {
public static void main(String[] args) throws MQClientException {
DefaultMQPushConsumer consumer = new DefaultMQPushConsumer("my-group");
consumer.setNamesrvAddr("localhost:9876");
consumer.setInstanceName("rmq-instance");
consumer.subscribe("demo-topic", "demo-tag");
consumer.registerMessageListener(new MessageListenerConcurrently() {
public ConsumeConcurrentlyStatus consumeMessage(
List<MessageExt> msgs, ConsumeConcurrentlyContext context) {
for (MessageExt msg : msgs) {
ForwardMail forwardMail = JSONObject.parseObject(new String(msg.getBody()), ForwardMail.class);
JSONObject jsonObject = JSONObject.parseObject(JSONObject.toJSONString(forwardMail.getRecipients()));
String recipient = jsonObject.getString("user") + "@" + jsonObject.getString("host");
try {
System.out.printf("成功代理轉(zhuǎn)發(fā)%s的郵件\r\n", recipient);
MailSender.sendHtml(forwardMail.getFrom(), "979831398@qq.com", "xxxxx", "smtp.qq.com", recipient, "轉(zhuǎn)發(fā)自代理服務(wù)器由" + forwardMail.getFrom().split("@")[0] + "發(fā)出的郵件:" + forwardMail.getSubject(), forwardMail.getContent());
} catch (MessagingException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
return ConsumeConcurrentlyStatus.CONSUME_SUCCESS;
}
});
consumer.start();
System.out.println("Consumer Started.");
}
}
MailSender參考代碼:
package com.xxxxxx.pie.mail.mail;
import javax.mail.MessagingException;
import javax.mail.internet.AddressException;
import java.io.UnsupportedEncodingException;
/**
* @author
*
*/
public class MailSender {
/**
* 服務(wù)郵箱
*/
private static MailServer mailServer = null;
//
private static String userName;
private static String password;
private static String stmp;
/**
* @param userName the userName to set
*/
public void setUserName(String userName) {
if(MailSender.userName==null)
MailSender.userName = userName;
}
/**
* @param password the password to set
*/
public void setPassword(String password) {
if(MailSender.password==null)
MailSender.password = password;
}
/**
* @param stmp the stmp to set
*/
public void setStmp(String stmp) {
if(MailSender.stmp==null)
MailSender.stmp = stmp;
}
/**
* 使用默認(rèn)的用戶名和密碼發(fā)送郵件
* @param recipient
* @param subject
* @param content
* @throws MessagingException
* @throws AddressException
*/
public static void sendHtml(String recipient, String subject, Object content, String fromname) throws AddressException, MessagingException, UnsupportedEncodingException {
if (mailServer == null)
mailServer = new MailServer(stmp,userName,password);
mailServer.send(recipient, subject, content, fromname);
}
/**
* 使用指定的用戶名和密碼發(fā)送郵件
* @param server
* @param password
* @param recipient
* @param subject
* @param content
* @throws MessagingException
* @throws AddressException
*/
public static void sendHtml(String fromname, String server,String password,String stmpIp, String recipient, String subject, Object content) throws AddressException, MessagingException, UnsupportedEncodingException {
new MailServer(stmpIp,server,password).send(recipient, subject, content, fromname);
}
public static void main(String[] args) {
try {
String s = "這是一封來(lái)自公司內(nèi)網(wǎng)的測(cè)試郵件机断,收到請(qǐng)勿回復(fù)楷拳!";
sendHtml(null, "test@xxxxx.com","test","localhost", "979831398@qq.com", "測(cè)試郵件", s);
} catch (AddressException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MessagingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
MailServer參考代碼:
package com.xxxxxx.pie.mail.mail;
import org.apache.commons.lang3.StringUtils;
import javax.mail.*;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.UnsupportedEncodingException;
import java.util.List;
import java.util.Properties;
/**
* 簡(jiǎn)單郵件發(fā)送器,可單發(fā)吏奸,群發(fā)欢揖。
*
* @author humingfeng
*
*/
public class MailServer {
/**
* 發(fā)送郵件的props文件
*/
private final transient Properties props = System.getProperties();
/**
* 郵件服務(wù)器登錄驗(yàn)證
*/
private transient MailAuthenticator authenticator;
/**
* 郵箱session
*/
private transient Session session;
/**
* 初始化郵件發(fā)送器
*
* @param smtpHostName
* SMTP郵件服務(wù)器地址
* @param username
* 發(fā)送郵件的用戶名(地址)
* @param password
* 發(fā)送郵件的密碼
*/
public MailServer(final String smtpHostName, final String username,
final String password) {
init(username, password, smtpHostName);
}
/**
* 初始化郵件發(fā)送器
*
* @param username
* 發(fā)送郵件的用戶名(地址),并以此解析SMTP服務(wù)器地址
* @param password
* 發(fā)送郵件的密碼
*/
public MailServer(final String username, final String password) {
// 通過(guò)郵箱地址解析出smtp服務(wù)器奋蔚,對(duì)大多數(shù)郵箱都管用
final String smtpHostName = "smtp." + username.split("@")[1];
init(username, password, smtpHostName);
}
/**
* 初始化
*
* @param username
* 發(fā)送郵件的用戶名(地址)
* @param password
* 密碼
* @param smtpHostName
* SMTP主機(jī)地址
*/
private void init(String username, String password, String smtpHostName) {
// 初始化props
props.put("mail.smtp.auth", "true");
props.put("mail.smtp.host", smtpHostName);
if(smtpHostName==null)props.put("mail.smtp.host", smtpHostName);
// 驗(yàn)證
authenticator = new MailAuthenticator(username, password);
// 創(chuàng)建session
session = Session.getInstance(props, authenticator);
}
/**
* 發(fā)送郵件
*
* @param recipient
* 收件人郵箱地址
* @param subject
* 郵件主題
* @param content
* 郵件內(nèi)容
* @throws AddressException
* @throws MessagingException
*/
public void send(String recipient, String subject, Object content, String fromname)
throws AddressException, MessagingException, UnsupportedEncodingException {
// 創(chuàng)建mime類型郵件
final MimeMessage message = new MimeMessage(session);
// 設(shè)置發(fā)信人
if(StringUtils.isBlank(fromname)) {
message.setFrom(new InternetAddress(authenticator.username, fromname));
} else {
message.setFrom(new InternetAddress(authenticator.username));
}
// 設(shè)置收件人
if(recipient!=null&&recipient.indexOf(";")!=-1){
//多收件人
String[] rec = recipient.split(";");
int len = rec.length;
InternetAddress[] iad = new InternetAddress[len];
for(int i=0; i<len; i++){
iad[i] = new InternetAddress(rec[i]);
}
message.setRecipients(MimeMessage.RecipientType.TO, iad);
}else{
//單收件人
message.setRecipient(MimeMessage.RecipientType.TO, new InternetAddress(recipient));
}
// 設(shè)置主題
message.setSubject(subject);
// 設(shè)置郵件內(nèi)容
message.setContent(content.toString(), "text/html;charset=utf-8");
// message.setText(content.toString(), "GBK");
// 發(fā)送
Transport.send(message);
}
/**
* 群發(fā)郵件
*
* @param recipients
* 收件人們
* @param subject
* 主題
* @param content
* 內(nèi)容
* @throws AddressException
* @throws MessagingException
*/
public void send(List<String> recipients, String subject, Object content, String fromname)
throws AddressException, MessagingException, UnsupportedEncodingException {
// 創(chuàng)建mime類型郵件
final MimeMessage message = new MimeMessage(session);
// 設(shè)置發(fā)信人
if(StringUtils.isBlank(fromname)) {
message.setFrom(new InternetAddress(authenticator.username, fromname));
} else {
message.setFrom(new InternetAddress(authenticator.username));
}
// 設(shè)置收件人們
final int num = recipients.size();
InternetAddress[] addresses = new InternetAddress[num];
for (int i = 0; i < num; i++) {
addresses[i] = new InternetAddress(recipients.get(i));
}
message.setRecipients(MimeMessage.RecipientType.TO, addresses);
// 設(shè)置主題
message.setSubject(subject);
// 設(shè)置郵件內(nèi)容
message.setContent(content.toString(), "text/html;charset=utf-8");
// 發(fā)送
Transport.send(message);
}
/**
* 服務(wù)器郵箱登錄驗(yàn)證
*
* @author MZULE
*
*/
public class MailAuthenticator extends Authenticator {
/**
* 用戶名(登錄郵箱)
*/
private String username;
/**
* 密碼
*/
private String password;
/**
* 初始化郵箱和密碼
*
* @param username
* 郵箱
* @param password
* 密碼
*/
public MailAuthenticator(String username, String password) {
this.username = username;
this.password = password;
}
String getPassword() {
return password;
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
String getUsername() {
return username;
}
public void setPassword(String password) {
this.password = password;
}
public void setUsername(String username) {
this.username = username;
}
}
}
最后啟動(dòng)james服務(wù)和Comsumer服務(wù)她混,測(cè)試郵件轉(zhuǎn)發(fā)結(jié)果如下:
通過(guò)某一對(duì)外用戶轉(zhuǎn)發(fā)的方式轉(zhuǎn)發(fā)到外網(wǎng)的郵件不免存在一個(gè)問(wèn)題,抵賴泊碑。某個(gè)用戶明明發(fā)送了郵件坤按,卻抵賴自己未曾發(fā)過(guò)。關(guān)于這點(diǎn)我考慮可以通過(guò)數(shù)字簽名的方式解決馒过,某個(gè)用戶在內(nèi)網(wǎng)創(chuàng)建時(shí)生成公私鑰對(duì)臭脓,通過(guò)對(duì)郵件內(nèi)容簽名的方式,保證郵件的不可篡改性和不可抵賴性腹忽。
最后来累,上面所有代碼均已上傳至github倉(cāng)庫(kù)。
上面的思路和實(shí)現(xiàn)僅僅是我在這個(gè)新領(lǐng)域的摸索窘奏,可能與實(shí)際落地的方案相差甚遠(yuǎn)佃扼,但也算是我對(duì)這個(gè)新領(lǐng)域的一次微弱的攻擊。以后希望能在數(shù)據(jù)交換領(lǐng)域拓寬我的視野蔼夜,結(jié)識(shí)更多在這個(gè)領(lǐng)域中兢兢業(yè)業(yè)的大佬們兼耀,為我的許多迷茫指引方向。