You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
178 lines
6.7 KiB
Java
178 lines
6.7 KiB
Java
// SMTPSender.java (C) K. J. Turner, P. K. Johnson 04/03/06
|
|
|
|
// Simple Mail Transfer Protocol sender (client)
|
|
|
|
package protocol;
|
|
|
|
import java.util.Vector;
|
|
import support.*;
|
|
|
|
public class SMTPSender implements ProtocolEntity {
|
|
|
|
private PDU pduReceived;
|
|
private PDU pduSent;
|
|
private ProtocolEntity peer;
|
|
private Medium medium;
|
|
private String name;
|
|
|
|
final static String clientData = "DATA";
|
|
final static String clientFrom = "MAIL FROM: sender";
|
|
final static String clientHello = "HELO client";
|
|
final static String clientMail = "Mail message";
|
|
final static String clientQuit = "QUIT";
|
|
final static String clientRecipient = "RCPT TO: recipient";
|
|
final static String invalidRecipient = "550 Recipient invalid";
|
|
final static String invalidSender = "550 Sender invalid";
|
|
final static String okRecipient = "250 Recipient OK";
|
|
final static String okSender = "250 Sender OK";
|
|
final static String serverAccept = "250 Message accepted";
|
|
final static String serverClosing = "221 Server Closing";
|
|
final static String serverHello = "250 Server hello to client";
|
|
final static String serverReady = "220 Server ready";
|
|
final static String serverSend = "354 Send mail";
|
|
final static String tcpConnect = "TCP connect";
|
|
final static String tcpDisconnect = "TCP disconnect";
|
|
|
|
int state; // protocol state
|
|
|
|
final static int idle = 0; // no connection
|
|
final static int waitReady = 1; // await server ready
|
|
final static int waitHello = 2; // await server hello
|
|
final static int ready = 3; // ready for mail
|
|
final static int waitSender = 4; // await sender answer
|
|
final static int waitRecipient = 5; // await recip answer
|
|
final static int waitSend = 6; // await server send
|
|
final static int waitAccept = 7; // await server accept
|
|
final static int waitClose = 8; // await server closing
|
|
|
|
int person = 1; // sender/recipient
|
|
int recipients; // number of recipients
|
|
|
|
public SMTPSender(Medium m, String name) {
|
|
this.name = name;
|
|
medium = m;
|
|
}
|
|
|
|
public String getName() {
|
|
return(name);
|
|
}
|
|
|
|
public Vector<String> getServices() {
|
|
Vector<String> list = new Vector<String>();
|
|
String pduType;
|
|
if (state == idle) // waiting to connect?
|
|
list.addElement(tcpConnect); // connect
|
|
else if (pduReceived != null) { // non-empty reply?
|
|
pduType = pduReceived.type; // get PDU type
|
|
if (state == waitReady && // awaiting server ready?
|
|
pduType.equals(serverReady)) // reply server ready?
|
|
list.addElement(clientHello); // send hello from client
|
|
else if (state == waitHello && // awaiting server hello?
|
|
pduType.equals(serverHello)) // reply server hello?
|
|
state = ready; // now ready
|
|
else if (state == waitSender) { // awaiting sender response?
|
|
if (pduType.equals(okSender)) { // sender is OK?
|
|
recipients = 0; // no recipients yet
|
|
state = waitSend; // now ready to send
|
|
}
|
|
else if (pduType.equals(invalidSender)) // sender is invalid?
|
|
state = ready; // back to ready
|
|
}
|
|
else if (state == waitRecipient && // awaiting recipient response?
|
|
(pduType.equals(okRecipient) || // recipient is OK or ...
|
|
pduType.equals(invalidRecipient))) { // not?
|
|
if (pduType.equals(okRecipient)) // recipient is OK?
|
|
recipients++; // add to recipients
|
|
state = waitSend; // still ready to send
|
|
}
|
|
else if (state == waitSend && // awaiting server send?
|
|
pduType.equals(serverSend)) { // response is server send?
|
|
list.addElement(clientMail); // send client mail message
|
|
state = waitAccept; // wait for server accept
|
|
}
|
|
else if (state == waitAccept && // awaiting server accept?
|
|
pduType.equals(serverAccept)) { // reply is server accept?
|
|
state = ready; // back to ready
|
|
}
|
|
else if (state == waitClose && // awaiting server closing?
|
|
pduType.equals(serverClosing)) { // reply is server closing?
|
|
list.addElement(tcpDisconnect); // disconnect
|
|
}
|
|
if (state == ready) { // ready?
|
|
list.addElement(clientFrom + person++); // propose sender
|
|
list.addElement(clientQuit); // propose quit
|
|
}
|
|
else if (state == waitSend) { // waiting to send?
|
|
list.addElement(clientRecipient + person++); // propose recipient
|
|
if (recipients > 0) // recipients?
|
|
list.addElement(clientData); // propose to send data
|
|
}
|
|
}
|
|
return(list);
|
|
}
|
|
|
|
public void initialise() {
|
|
state = idle; // initialise state
|
|
pduReceived = null; // note no PDU received
|
|
person = 1; // initialise sender/recipient
|
|
}
|
|
|
|
public Vector<ProtocolEvent> performService(String s) {
|
|
Vector<ProtocolEvent> events = new Vector<ProtocolEvent>();
|
|
if (s.equals(clientData)) { // send client data?
|
|
transmitPDU(new PDU(clientData), peer); // send client data
|
|
state = waitSend; // await server send
|
|
}
|
|
else if (s.startsWith(clientFrom)) { // send sender?
|
|
transmitPDU(new PDU(s), peer); // send sender
|
|
state = waitSender; // await sender response
|
|
}
|
|
else if (s.equals(clientHello)) { // send client hello?
|
|
transmitPDU(new PDU(s), peer); // send client hello
|
|
state = waitHello; // await server hello
|
|
}
|
|
else if (s.equals(clientMail)) // send client mail message?
|
|
transmitPDU(new PDU(clientMail), peer); // send client mail message
|
|
else if (s.equals(clientQuit)) { // send client quit?
|
|
transmitPDU(new PDU(clientQuit), peer); // send client quit
|
|
state = waitClose; // await server closing
|
|
}
|
|
else if (s.startsWith(clientRecipient)) { // send recipient?
|
|
transmitPDU(new PDU(s), peer); // send recipient
|
|
state = waitRecipient; // await recipient response
|
|
}
|
|
if (s.equals(tcpConnect)) { // send TCP connect?
|
|
transmitPDU(new PDU(tcpConnect), peer); // send TCP connect
|
|
state = waitReady; // await server ready
|
|
}
|
|
else if (s.equals(tcpDisconnect)) { // send TCP disconnect?
|
|
transmitPDU(new PDU(tcpDisconnect), peer); // send TCP disconnect
|
|
state = idle; // back to start
|
|
}
|
|
if (pduSent != null) { // PDU to send?
|
|
events.addElement(new ProtocolEvent(ProtocolEvent.TRANSMIT, pduSent));
|
|
events.addElement(new ProtocolEvent(ProtocolEvent.RECEIVE, pduSent));
|
|
}
|
|
pduSent = null; // nullify just in case
|
|
return(events);
|
|
}
|
|
|
|
public Vector<ProtocolEvent> receivePDU(PDU pdu) {
|
|
pduReceived = pdu;
|
|
return(new Vector<ProtocolEvent>());
|
|
}
|
|
|
|
public void transmitPDU(PDU pdu, ProtocolEntity dest) {
|
|
pdu.setSource(this);
|
|
pdu.setDestination(dest);
|
|
pduSent = pdu;
|
|
this.peer.receivePDU(pdu);
|
|
pduReceived = null;
|
|
}
|
|
|
|
public void setPeer(ProtocolEntity peer) {
|
|
this.peer = peer;
|
|
}
|
|
|
|
}
|