Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TOREVIEW] StmpClient done #2

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ buildNumber.properties
.mvn/timing.properties
# https://github.com/takari/maven-wrapper#usage-without-binary-jar
.mvn/wrapper/maven-wrapper.jar
.idea/
out/
src/test/
Teaching-HEIGVD-RES-2021-Labo-SMTP.iml
68 changes: 30 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,53 @@
# Teaching-HEIGVD-RES-2021-Labo-SMTP

## Objectives
## Introduction

In this lab, you will develop a client application (TCP) in Java. This client application will use the Socket API to communicate with an SMTP server. The code that you write will include a **partial implementation of the SMTP protocol**. These are the objectives of the lab:
__Spammer__ is a prank-application. With a given victim list and a give number of groups, the application will send provided messages to victims by group with another victim email chosen randomly in each group. In other words, the goal is to mislead recipient victims into thinking that the sender victim has sent them. __Spammer__ uses the Socket API to communicate with an SMTP server with TCP connection in Java. (It is notable that the application is a **partial implementation of the SMTP protocol**.)

* Make practical experiments to become familiar with the **SMTP protocol**. After the lab, you should be able to use a command line tool to **communicate with an SMTP server**. You should be able to send well-formed messages to the server, in order to send emails to the address of your choice.
## Instructions

* Understand the notions of **test double** and **mock server**, which are useful when developing and testing a client-server application. During the lab, you will setup and use such a **mock server**.
There are 3 configuration files in which you are free to set values as you want as long as these values obey their standard formats :

* Understand what it means to **implement the SMTP protocol** and be able to send e-mail messages, by working directly on top of the Socket API (i.e. you are not allowed to use a SMTP library).
1. __config.properties__: contains server properties.
* ___smtpServerAddress___ : determines SMTP server addresses.
* ___smtpServerPort___: determines SMTP server port. If the value less or equal than 0, the port will be 25 by default.
* ___numberOfGroups___: number of groups that you want to partition victim list.
* ___chosenGroupsForPrank___: groups of victims that you want to do the prank on. If the value is 0, the prank will be made on all groups.
* ___witnessesToCC___: CC email for the prank. If the value is `none`, the CC email will be considered as `null`.

* **See how easy it is to send forged e-mails**, which appear to be sent by certain people but in reality are issued by malicious users.
2. __messages.uft8__: contains given messages which will be encoded in `utf-8` of the prank. The file can contain multiple paragraphs. If there are 10 equal symbols (`==========`) separating them. All the paragraphs between these symbols represent a message. By convention, the first line of paragraph is the message subject and the rest is the message content.
3. __victims.uft8__: contains a victim email list also provided and encoded in `utf-8`. This list will be partitioned into small groups. Note that in every group of victims, there should be 1 sender and at least 2 recipients (i.e. the minimum size for a group is 3). In the file, each line must contain exactly one victim email address.

* **Design a simple object-oriented model** to implement the functional requirements described in the next paragraph.
All these files are found in `data` folder.

On the other hand, once the groups are created. They will be written in `groups.utf8` file, which can be found in `target/out/`. In this file, you'll find who the sender of each group and his recipients. Each group is separated by 10 equal symbols (`==========`).

## Functional requirements
The application will choose randomly a message and a sender for each group.

Your mission is to develop a client application that automatically plays pranks on a list of victims:
## Mock SMTP server

* The user should be able to **define a list of victims** (concretely, you should be able to create a file containing a list of e-mail addresses).
* The user should be able to **define how many groups of victims should be formed** in a given campaign. In every group of victims, there should be 1 sender and at least 2 recipients (i.e. the minimum size for a group is 3).
* The user should be able to **define a list of e-mail messages**. When a prank is played on a group of victims, then one of these messages should be selected. **The mail should be sent to all group recipients, from the address of the group sender**. In other words, the recipient victims should be lead to believe that the sender victim has sent them.
This section is for those who want to experiment with __Spammer__ but don't really want to send pranks immediately.

## Constraints
First of all, you will need to simulate a ___fake___ SMTP server, i.e., mock SMTP server.
> A [MockServer](<https://en.wikipedia.org/wiki/MockServer#:~:text=MockServer%20is%20designed%20to%20simplify,not%20complete%20or%20is%20unstable.>) is designed to simplify integration testing and promotes best practices by improving the isolation of the system under test.

- The goal is for you to work at the wire protocol level (with the Socket API). Therefore, you CANNOT use a library that takes care of the protocol details. You have to work with the input and output streams.
- The program must be configurable: the addresses, groups, messages CANNOT be hard-coded in the program and MUST be managed in config files.
In order to do that, you can use any mock SMTP server on the internet. Here, we'll use [MockMock server](<https://github.com/tweakers/MockMock>) on GitHub, which is a web-application. The executable `jar` file can be easily downloaded by following the instructions in `README.md` of [MockMock server](<https://github.com/tweakers/MockMock>) or retrieved by cloning the repository then building application. For any further information, you can checkout [MockMock server](<https://github.com/tweakers/MockMock>) repository.

Once you have extracted the executable file to any place that you like, you can start the server by running: `java -jar MockMock.jar`. Note that with this command, the port is 25 by default. To run MockMock on another port, you can start it with the following parameters: `java -jar MockMock.jar -p 25000 -h 8080`. This will run MockMock on SMTP port 25000 and http port 8080. After that, you can go to your browser and type `localhost:8282`. This will show you the web interface of MockMock.

## Example
You can now launch __Spammer__ which will read your configuration in 3 files mentioned above. After refreshing the browser you'll see the prank made on your victim list.

Consider that your program generates a group G1. The group sender is Bob. The group recipients are Alice, Claire and Peter. When the prank is played on group G1, then your program should pick one of the fake messages. It should communicate with an SMTP server, so that Alice, Claire and Peter receive an e-mail, which appears to be sent by Bob.
## Description of implementation
![Simplified UML of __Spammer__](https://github.com/mhganh/Teaching-HEIGVD-RES-2021-Labo-SMTP/tree/main/figures/schema.png?raw=true "Simplified UML of __Spammer__ without Utils and Exceptions")

## Teams
The logic of the application remains in 2 classes: `ConfigurationManager` and `PrankGenerator`.

You may work in teams of 2 students.
The first class is responsible for reading configuration files in __Instruction__ section. For the messages, it will call create a `MessageList` to obtain messages in the message file by reading all characters in the file (Remember that each message is separated by 10 equal symbols (`==========`)), then, split the result string by the convention separation into substrings, which are the messages. For the victims, the principle is as same as for the messages, `ConfigurationManager` creates a `VictimList`, which save the victims by reading the victim file line by line. For the server properties, `ConfigurationManager` creates a `ServerProperties` to set up the server with the help of `Properties`.

## Deliverables
The second class is used for partitioning the victim list and generating mails/pranks based on configurations above. The partition is quite easy. It just creates groups with size of victim list divided by the given number of groups. Then, for each group, it will randomly choose a victim sender and recipient and also a message for each prank.

You will deliver the results of your lab in a GitHub repository. You do not have to fork a specific repo, you can create one from scratch.

Your repository should contain both the source code of your Java project and your report. Your report should be a single `README.md` file, located at the root of your repository. The images should be placed in a `figures` directory.

Your report MUST include the following sections:

* **A brief description of your project**: if people exploring GitHub find your repo, without a prior knowledge of the RES course, they should be able to understand what your repo is all about and whether they should look at it more closely.

* **Instructions for setting up a mock SMTP server (with Docker - which you will learn all about in the next 2 weeks)**. The user who wants to experiment with your tool but does not really want to send pranks immediately should be able to use a mock SMTP server. For people who are not familiar with this concept, explain it to them in simple terms. Explain which mock server you have used and how you have set it up.

* **Clear and simple instructions for configuring your tool and running a prank campaign**. If you do a good job, an external user should be able to clone your repo, edit a couple of files and send a batch of e-mails in less than 10 minutes.

* **A description of your implementation**: document the key aspects of your code. It is probably a good idea to start with a class diagram. Decide which classes you want to show (focus on the important ones) and describe their responsibilities in text. It is also certainly a good idea to include examples of dialogues between your client and an SMTP server (maybe you also want to include some screenshots here).
## References

* [MockMock server](<https://github.com/tweakers/MockMock>) on GitHub. Pay attention to this [pull request](https://github.com/tweakers/MockMock/pull/8). While it has not been merged, it will give you the solution to compile the project on your machine.
* The [mailtrap](<https://mailtrap.io/>) online service for testing SMTP
* The [SMTP RFC](<https://tools.ietf.org/html/rfc5321#appendix-D>), and in particular the [example scenario](<https://tools.ietf.org/html/rfc5321#appendix-D>)
* Testing SMTP with TLS: `openssl s_client -connect smtp.mailtrap.io:2525 -starttls smtp -crlf`

* [MockMock server](<https://github.com/tweakers/MockMock>) on GitHub
* [MockServer](<https://en.wikipedia.org/wiki/MockServer#:~:text=MockServer%20is%20designed%20to%20simplify,not%20complete%20or%20is%20unstable.>) on Wikipedia
* [Regex for email](<https://howtodoinjava.com/java/regex/java-regex-validate-email-address/>)
5 changes: 5 additions & 0 deletions data/config.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
smtpServerAddress=localhost
smtpServerPort=25
numberOfGroups=6
chosenGroupsForPrank=0
witnessesToCC=NONE
12 changes: 12 additions & 0 deletions data/messages.utf8
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Subject: Parler derrière mon dos
Ca va? T'as bien parlé derrière mon dos? Et à part ça, on parle de confiance!
Je pensais vraiment pas que t'étais comme ça! Tu t'es bien foutu de moi!
Pourquoi t'es allé raconter à tout le monde que le Père Noël n'existait pas?
==========
Subject: Recherche cerveau
Message important : Votre mobile est en train de mettre à jour votre cerveau...
Recherche cerveau en cours...recherche...recherche...procédure échouée...aucun cerveau trouvé !
==========
Subject: Journée mondiale de la grippe aviaire
Aujourd'hui, c'est la journée mondiale de la lutte contre la grippe aviaire.
Envoi ce message de solidarité à un dindon ou une pintade que tu connais...voilà, moi de mon côté c'est fait...
87 changes: 87 additions & 0 deletions data/victims.utf8
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
Binary file added figures/schema.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
29 changes: 29 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?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>Teaching-HEIGVD-RES-2021-Labo-SMTP</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.0-M1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>

<properties>
<maven.compiler.source>15</maven.compiler.source>
<maven.compiler.target>15</maven.compiler.target>
</properties>

</project>
43 changes: 43 additions & 0 deletions src/main/java/Spammer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import config.ConfigurationManager;
import config.ServerProperties;
import model.exception.*;
import model.prank.Prank;
import model.prank.PrankGenerator;
import smtp.SmtpClient;

import java.io.IOException;
import java.util.ArrayList;

public class Spammer {

public static void main(String... args) throws EmptyList, IOException, IncorrectFormatEmail, GroupMinimumSizeException, SmtpException, NoGroupCreated {
ConfigurationManager config = new ConfigurationManager();
PrankGenerator pg = new PrankGenerator(config);

pg.generateGroups();
ArrayList<Prank> pranks = pg.generatePranks();

ServerProperties server = config.getServerProperties();
String address = server.getServerAddress();
int port = server.getServerPort();
int nbGroups = server.getNbVictimGroups();

SmtpClient smtp = new SmtpClient(address, port);

if(server.getChosenGroups()[0] == 0) {
for(Prank p : pranks) {
smtp.sendMessage(p);
}
} else {
int[] ids = server.getChosenGroups();
for (int id : ids) {
int groupId = id - 1;
if (groupId < nbGroups) {
smtp.sendMessage(pranks.get(groupId));
} else {
throw new IndexOutOfBoundsException("GroupId exceeds the number of groups");
}
}
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/config/ConfigurationManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package config;

import model.exception.EmptyList;
import model.exception.IncorrectFormatEmail;

import java.io.IOException;

public class ConfigurationManager {
private final ServerProperties serverProperties;
private final MessageList messageList;
private final VictimList victimList;

public ConfigurationManager() throws EmptyList, IOException, IncorrectFormatEmail {
serverProperties = new ServerProperties("data/config.properties");
serverProperties.loadFromFile();

messageList = new MessageList("data/messages.utf8");
victimList = new VictimList("data/victims.utf8");
}

public ServerProperties getServerProperties() {
return serverProperties;
}

public MessageList getMessageList() {
return messageList;
}

public VictimList getVictimList() {
return victimList;
}
}
Loading