Index: pages/api/postgre/activate/[id].js
===================================================================
--- pages/api/postgre/activate/[id].js	(revision e007fcdfa1962fb2f1a22d233c554eec360f982b)
+++ pages/api/postgre/activate/[id].js	(revision e007fcdfa1962fb2f1a22d233c554eec360f982b)
@@ -0,0 +1,29 @@
+import axios from "axios";
+
+export default function handler(req, res) {
+    /**
+     * GET method
+     */
+    if (req.method === 'GET') {
+        /**
+         * /---------------------- GET ----------------------/
+         * Activate account
+         * @action activate_account
+         * @param id emailActivationId
+         */
+        if (req.query?.action === 'activate_account' && req.query?.id) {
+            const emailActivationId = req.query.id
+
+            axios.get(`${process.env.HOME_URL}/api/postgre/?action=activate_account&emailActivationId=${emailActivationId}`).then(postgreRes => {
+                if (postgreRes.data?.success) {
+                    res.json({
+                        success: true,
+                    })
+                }
+                else {
+                    res.end();
+                }
+            });
+        }
+    }
+}
Index: pages/api/postgre/index.js
===================================================================
--- pages/api/postgre/index.js	(revision 55701f0270de2168597a7ca5d1a05ae6a66f516b)
+++ pages/api/postgre/index.js	(revision e007fcdfa1962fb2f1a22d233c554eec360f982b)
@@ -6,4 +6,6 @@
 
 const crypto = require('crypto');
+
+const nodemailer = require('nodemailer');
 
 import { progressRoundTillTheEnd } from '../poker/tableSpecific';
@@ -214,4 +216,31 @@
     /**
      * /---------------------- GET ----------------------/
+     * Activates an user account if not activated.
+     * @action activate_account
+     * @param emailActivationId
+     */
+    if (req.query?.action === 'activate_account' && req.query?.emailActivationId) {
+      pool.query('SELECT * FROM users WHERE email_activation_id = $1', [req.query.emailActivationId], (error, results) => {
+        if (error) throw error;
+
+        if (results.rows.length > 0) {
+          pool.query('UPDATE users SET activated = $1 WHERE email_activation_id = $2', [true, req.query.emailActivationId], (error, results) => {
+            if (error) throw error;
+
+            res.json({
+              success: true,
+            })
+          });
+        }
+        else {
+          res.json({
+            success: false,
+          })
+        }
+      });
+    }
+
+    /**
+     * /---------------------- GET ----------------------/
      * Checks if the player is logged in, and returns his session if so.
      * @action check_if_logged_in
@@ -226,4 +255,5 @@
           success: true,
           displayName: session.displayName,
+          username: session.username,
           session_id: session.id,
           credits: session.credits,
@@ -254,8 +284,25 @@
 
         sessions.splice(sessions.indexOf(session), 1);
-
-        axios.get(`${process.env.HOME_URL}/api/blackjack/?action=remove_room&session_id=${session_id}`);
-
         update_sessions_to_database();
+
+        // remove player from games:
+        if (rooms[session_id] !== undefined) {
+          delete rooms[session_id];
+          update_rooms_to_database();
+        }
+
+        if (game.players?.map(e=>e.session_id).indexOf(session_id) !== -1) {
+          game.players?.splice(game.players?.map(e=>e.session_id).indexOf(session_id), 1);
+          update_game_to_database();
+        }
+
+        tables.forEach(table => {
+          table.players?.forEach(player => {
+            if (player.id === session_id) {
+              player.isGhost = true;
+            }
+          })
+        })
+        update_tables_to_database();
       }
 
@@ -480,4 +527,18 @@
     if (body?.action === 'register') {
       // checks
+      if (body?.email == "undefined" || body?.email == "null" || body?.email == "") {
+        res.json({
+          success: false,
+          message: 'Email is required',
+        });
+        return ;
+      }
+      if (!body?.email?.includes('@') || body?.email?.indexOf('@', body?.email?.indexOf('@')+1) !== -1) {
+        res.json({
+          success: false,
+          message: 'Not a valid email',
+        });
+        return ;
+      }
       if (body?.username == "undefined" || body?.username == "null" || body?.username == "") {
         res.json({
@@ -535,6 +596,8 @@
         }
 
+        const emailActivationId = uuidv4();
+
         // store user in database
-        pool.query('INSERT INTO users (username, password, salt) VALUES ($1, $2, $3)', [body.username, hashedPassword, salt], (error, usersResults) => {
+        pool.query('INSERT INTO users (username, password, salt, email, email_activation_id, activated) VALUES ($1, $2, $3, $4, $5, $6)', [body.username, hashedPassword, salt, body.email, emailActivationId, false], (error, usersResults) => {
           if (error) throw error;
 
@@ -544,4 +607,6 @@
             pool.query('INSERT INTO stats (username, blackjack_games, roulette_games, poker_games, blackjack_won_games, roulette_won_games, poker_won_games, money_bet, money_earned) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)', [body.username, 0, 0, 0, 0, 0, 0, 0, 0], (error, statsResults) => {
               if (error) throw error;
+
+              sendMailForActivation(body.displayName, body.email, emailActivationId);
 
               res.json({
@@ -604,8 +669,18 @@
           if (usersResults.rows.length > 0) {
             const user = usersResults.rows[0];
+
             const salt = user.salt;
             const hashedPassword = crypto.pbkdf2Sync(body.password, salt, 1000, 64, 'sha512').toString('hex');
 
             if (hashedPassword === user.password) {
+              if (user.activated === "false") {
+                res.json({
+                  success: false,
+                  message: 'Account not activated. Check your email.',
+                })
+
+                return ;
+              }
+
               pool.query('SELECT * FROM players WHERE username = $1', [body.username], (error, playersResults) => {
                 if (playersResults.rows.length > 0) {
@@ -658,4 +733,83 @@
 }
 
+// Mailing
+const transporter = nodemailer.createTransport({
+  service: 'gmail',
+  auth: {
+      user: process.env.GOOGLE_EMAIL,
+      pass: process.env.GOOGLE_APP_PASSWORD,
+  }
+})
+
+function sendMailForActivation(displayName, userEmail, emailActivationId) {
+  const message = {
+      from: process.env.GOOGLE_EMAIL,
+      to: userEmail,
+      subject: "Caessino - Activate your account",
+      html: `
+          <h4>Hello, ${displayName}</h4>
+          <p>Thank you for creating an account at Caessino. Just one more step and you can start enjoying the games!</p>
+          <p>To activate your account please follow this link: <a target="_blank" href="${process.env.HOME_URL}/activate/${emailActivationId}">Activate account</a>
+          <br/>
+          <p>Cheers and happy playing,</p>
+          <p>The Team ESS</p>
+      `
+  }
+
+  transporter.sendMail(message, (err, data) => {
+      if (err) {
+          console.log(err);
+      }
+  })
+}
+
+let mailSentTo = {
+  poker: [],
+  roulette: [],
+  blackjack: [],
+}
+function sendMailForGameCompletition(game, username, displayName) {
+  return ;
+
+  const msgPoker = 'Your game was played to the end by the computer with the following rules:<br/>1. No more bets were made by any player;<br/>2. Cards were dealt normally like they would be under normal circumstances;<br/>3. Credits were given to the winners and taken from the losers.';
+  const msgRoulette = 'If you reconnect immediately, you can catch this ongoing game. But don\'t worry if you can\'t! If you win, credits will be awarded to you.';
+  const msgBlackjack = 'You can now continue playing your game.';
+  
+  pool.query('SELECT * FROM users WHERE username = $1', [username], (error, results) => {
+    if (error) throw error;
+
+    if (results.rows.length > 0) {
+      const userEmail = results.rows[0].email;
+
+      if ((game === 'poker' && mailSentTo.poker.indexOf(userEmail) === -1) ||
+          (game === 'roulette' && mailSentTo.roulette.indexOf(userEmail) === -1) ||
+          (game === 'blackjack' && mailSentTo.blackjack.indexOf(userEmail) === -1))
+      {
+        const message = {
+          from: process.env.GOOGLE_EMAIL,
+          to: userEmail,
+          subject: "Caessino - Server is back online",
+          html: `
+            <h4>Hello, ${displayName}</h4>
+            <p>We are writing to inform you that the server is back online.</p>
+            <p>We know that you were in the middle of playing ${game}, and we apologize for the interrupt.</p>
+            <p>${game === 'poker' ? msgPoker : game === 'roulette' ? msgRoulette : msgBlackjack}</p>
+            <br/>
+            <p>All the best,</p>
+            <p>The Team ESS</p>
+            `
+        }
+
+        transporter.sendMail(message, (err, data) => {
+          if (err) {
+              console.log(err);
+          }
+        })
+
+        mailSentTo[game].push(userEmail)
+      }
+    }
+  });
+}
 
 /**
@@ -708,4 +862,14 @@
     })
 
+    tables.forEach(table => {
+      if (table.ended) {
+        table.players?.forEach(player => {
+          if (!player.isGhost) {
+            sendMailForGameCompletition('poker', player.username, player.displayName);
+          }
+        })
+      }
+    })
+
     cleanTables();
 
@@ -731,4 +895,8 @@
 
     game = JSON.parse(results?.rows[0]?.data || []);
+
+    game.players?.forEach(player => {
+      sendMailForGameCompletition('roulette', player.username, player.name);
+    })
 
     game.loaded = true;
@@ -767,4 +935,8 @@
         rooms[room.id] = {...room, id: ''}
       })
+
+      tmpRooms.forEach(room => {
+        sendMailForGameCompletition('blackjack', room.username, room.displayName);
+      })
       
       rooms["loaded"] = true;
