// Feeds FILIUS' SMTP and POP3 workers (SMTPMitarbeiter, POP3Mitarbeiter of // an EmailServer) with messages from a client, one after the other, without // a network: the worker's socket only writes down what it is to send. After // each message it writes what the worker sent, the lines the e-mail server // wrote into its window, whether the socket was closed, and the accounts // (each message as Email.toString, new, marked for deletion). The reference // for the core's e-mail server (packages/core/src/runtime/apps/emailServer.ts). // Each case starts from a new server with the accounts of EmailRun (domain // filius.de, its address 192.168.0.30, the client 192.168.0.20). The cases // file is ASCII, with Java-style unicode escapes (backslash, u, four hex // digits) for anything else, a message per line: // // case smtp|pop3 // // // Usage: java -cp filius.jar:lib/*:classes MailCases import filius.hardware.knoten.Rechner; import filius.rahmenprogramm.Information; import filius.software.email.Email; import filius.software.email.EmailKonto; import filius.software.email.EmailServer; import filius.software.email.POP3Mitarbeiter; import filius.software.email.POP3Server; import filius.software.email.SMTPMitarbeiter; import filius.software.email.SMTPServer; import filius.software.system.Datei; import filius.software.system.InternetKnotenBetriebssystem; import filius.software.transportschicht.TCPSocket; import java.io.FileOutputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; public class MailCases { /** A socket that only writes down what is sent, and whether it was closed. */ static class Recorder extends TCPSocket { final List sent = new ArrayList<>(); boolean closed = false; Recorder(InternetKnotenBetriebssystem system) throws Exception { super(system, "192.168.0.20", 50000); } @Override public synchronized void senden(String nachricht) { sent.add(nachricht); } @Override public void schliessen() { closed = true; } @Override public void beenden() { closed = true; } @Override public boolean istVerbunden() { return !closed; } @Override public String holeZielIPAdresse() { return "192.168.0.20"; } } public static void main(String[] args) throws Exception { // Before any class reads the message bundle (I18n.messages is read once). Information.getInformation().setLocale(args[0].equals("en") ? new Locale("en", "GB") : Locale.GERMANY); List cases = new ArrayList<>(); List steps = null; EmailServer server = null; Recorder socket = null; Object worker = null; Method process = null; List lines = new ArrayList<>(); for (String line : Files.readAllLines(Path.of(args[1]), StandardCharsets.US_ASCII)) { if (line.isEmpty() || line.startsWith("#")) continue; if (line.startsWith("case ")) { String[] words = line.split(" "); Map current = new LinkedHashMap<>(); steps = new ArrayList<>(); current.put("name", words[1]); current.put("protocol", words[2]); current.put("steps", steps); cases.add(current); Rechner host = new Rechner(); InternetKnotenBetriebssystem system = (InternetKnotenBetriebssystem) host.getSystemSoftware(); system.setzeIPAdresse("192.168.0.30"); system.installApp("filius.software.email.EmailServer", false); server = (EmailServer) system.holeSoftware("filius.software.email.EmailServer"); system.getDateisystem().speicherDatei("/mailserver", new Datei("konten.txt", "txt", EmailRun.ACCOUNTS)); server.setMailDomain("filius.de"); server.kontenLaden(); lines.clear(); List window = lines; server.hinzuBeobachter((observable, data) -> { if (data != null) window.add(String.valueOf(data)); }); socket = new Recorder(system); if (words[2].equals("smtp")) { worker = new SMTPMitarbeiter(socket, new SMTPServer(25, server)); process = SMTPMitarbeiter.class.getDeclaredMethod("verarbeiteNachricht", String.class); } else { worker = new POP3Mitarbeiter(socket, new POP3Server(110, server)); process = POP3Mitarbeiter.class.getDeclaredMethod("verarbeiteNachricht", String.class); } process.setAccessible(true); // The greeting the worker sends when it begins. steps.add(step(null, socket, lines, server, null)); continue; } String message = IpCheckCases.unescape(line); String thrown = null; try { process.invoke(worker, message); } catch (InvocationTargetException error) { thrown = error.getCause().getClass().getSimpleName(); } steps.add(step(message, socket, lines, server, thrown)); } try (FileOutputStream out = new FileOutputStream(args[2])) { out.write((FlsOracle.Json.write(cases, "") + "\n").getBytes(StandardCharsets.UTF_8)); } System.out.println("mail cases (" + args[0] + "): " + cases.size()); System.exit(0); } static Map step(String message, Recorder socket, List lines, EmailServer server, String thrown) { Map step = new LinkedHashMap<>(); step.put("message", message); step.put("sent", new ArrayList<>(socket.sent)); step.put("lines", new ArrayList<>(lines)); step.put("closed", socket.closed); step.put("thrown", thrown); List accounts = new ArrayList<>(); for (EmailKonto account : server.getListeBenutzerkonten()) { List messages = new ArrayList<>(); for (Email email : account.getNachrichten()) messages.add(Arrays.asList(email.toString(), email.getNeu(), email.getDelete())); accounts.add(Arrays.asList(account.getBenutzername(), messages)); } step.put("accounts", accounts); socket.sent.clear(); lines.clear(); return step; } }