diff --git a/canapGEST/API/app/Helpers/AccessLevelHelper.php b/canapGEST/API/app/Helpers/AccessLevelHelper.php
index a4437d5a47ee1ef2a3ddaaedc9c5dae5cf27c06e..ca00e43c6db476c6b5aeeeb587eb7e5bb2fbb755 100644
--- a/canapGEST/API/app/Helpers/AccessLevelHelper.php
+++ b/canapGEST/API/app/Helpers/AccessLevelHelper.php
@@ -71,8 +71,8 @@ class AccessLevelHelper
 
   public static function isResponsible($user_groups)
   {
-    $responsible_default_group = 'apprentis-informaticiens';
-    // $responsible_default_group = 'responsables-apprentis';
+    // $responsible_default_group = 'apprentis-informaticiens';
+    $responsible_default_group = 'responsables-apprentis';
     return in_array($responsible_default_group, $user_groups);
   }
 }
\ No newline at end of file
diff --git a/canapGEST/API/app/Http/Controllers/ApplicantsController.php b/canapGEST/API/app/Http/Controllers/ApplicantsController.php
index 83a0b97d58090acac962d0cd2898cf528df5aeec..289013ece73e0c98f3db4bcedb3df8995db24948 100644
--- a/canapGEST/API/app/Http/Controllers/ApplicantsController.php
+++ b/canapGEST/API/app/Http/Controllers/ApplicantsController.php
@@ -8,6 +8,7 @@ use Illuminate\Support\Facades\DB;
 use App\Helpers\AccessLevelHelper;
 use Illuminate\Support\Facades\Lang;
 use Illuminate\Support\Facades\File;
+use ZipArchive;
 
 class ApplicantsController extends Controller
 {
@@ -115,18 +116,31 @@ class ApplicantsController extends Controller
 
   public function export($id)
   {
+    // export data (json) and files in a .zip file
     $applicant_job = $this->getApplicantJob($id);
     $has_access = AccessLevelHelper::hasAccessToJob($applicant_job, $this->user_permissions);
     if ($has_access) {
-      $tmp_file_path = sys_get_temp_dir() . '\\' .$id .'-export.json';
+      $tmp_dir = sys_get_temp_dir();
+      $zipFileName = $id.'export.zip';
+      $zip = new ZipArchive;
+
+      $tmp_file_path = $tmp_dir . '\\' .$id .'-export.json';
       $json = AccessLevelHelper::hasPermittedRole($this->user_role, 'formateur') ? json_encode($this->getOne($id, true)) : json_encode($this->getOne($id, false));
-      if (json_decode($json)->personal_data == null) {
-        return response()->json(['error' => 403, 'message' => lang::get('http.unauthorized')], 403);
-      }
       File::put($tmp_file_path, $json);
-      return response()->download($tmp_file_path, $id .'-export.json', ['Content-Type' => 'application/json'])->deleteFileAfterSend(true);
-    } else {
-      return response()->json(['error' => 403, 'message' => lang::get('http.unauthorized')], 403);
+
+      $applicant_files = DB::table('file')
+      ->where('fk_applicant_id', $id)->get();
+
+      if ($zip->open($tmp_dir . '/' . $zipFileName, ZipArchive::CREATE) === TRUE) {
+        foreach ($applicant_files as $file) {
+          $zip->addFile($file->file_path, $file->file_name);
+        }
+        $zip->addFile($tmp_file_path, 'data.json');
+        $zip->close();
+      }
+
+      $export_path = $tmp_dir .'/'. $zipFileName;
+      return response()->download($export_path, $id .'export.zip', ['Content-Type' => 'application/zip'])->deleteFileAfterSend(true);
     }
   }
 
diff --git a/canapGEST/API/app/Http/Controllers/FilesController.php b/canapGEST/API/app/Http/Controllers/FilesController.php
index 00004d8c1fbb57397bcb7230e6a0bf7193934c4c..1a8ad458299ac7983f1876f31e1720b79a271691 100644
--- a/canapGEST/API/app/Http/Controllers/FilesController.php
+++ b/canapGEST/API/app/Http/Controllers/FilesController.php
@@ -8,6 +8,7 @@ use Illuminate\Http\Reponse;
 use Illuminate\Support\Facades\DB;
 use App\Helpers\AccessLevelHelper;
 use Illuminate\Support\Facades\Lang;
+use ZipArchive;
 
 class FilesController extends Controller
 {
@@ -22,7 +23,6 @@ class FilesController extends Controller
 
   public function getFile($id)
   {
-    // Deprecated
     // Check access to file
     $applicant_job = DB::table('applicant')
       ->join('file', 'file.fk_applicant_id', '=', 'applicant.applicant_id')
@@ -38,4 +38,32 @@ class FilesController extends Controller
       return response()->json(['error' => 403, 'message' => lang::get('http.unauthorized')], 403);
     }
   }
+
+  public function exportApplicantFiles($id)
+  {
+    $applicant_job = DB::table('applicant')
+    ->join('file', 'file.fk_applicant_id', '=', 'applicant.applicant_id')
+    ->join('position', 'applicant.fk_position', '=', 'position.position_id')
+    ->join('job', 'position.fk_job', '=', 'job.job_id')
+    ->where('applicant_id', $id)->pluck('job_short_value')->first();
+    $has_access = AccessLevelHelper::hasAccessToJob($applicant_job, $this->user_permissions);
+    if ($has_access) {
+      $tmp_dir = sys_get_temp_dir();
+      $zipFileName = $id.'export.zip';
+      $zip = new ZipArchive;
+
+      $applicant_files = DB::table('file')
+      ->where('fk_applicant_id', $id)->get();
+
+      if ($zip->open($tmp_dir . '/' . $zipFileName, ZipArchive::CREATE) === TRUE) {
+        foreach ($applicant_files as $file) {
+          $zip->addFile($file->file_path, $file->file_name);
+        }
+        $zip->close();
+      }
+
+      $export_path = $tmp_dir .'/'. $zipFileName;
+      return response()->download($export_path, $id .'export-annexes.zip', ['Content-Type' => 'application/zip'])->deleteFileAfterSend(true);
+    }
+  }
 }
diff --git a/canapGEST/API/app/Http/Controllers/MailsController.php b/canapGEST/API/app/Http/Controllers/MailsController.php
new file mode 100644
index 0000000000000000000000000000000000000000..475b7c5e3088676f76afc7a0e70427785be30bd6
--- /dev/null
+++ b/canapGEST/API/app/Http/Controllers/MailsController.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use Laravel\Lumen\Routing\Controller;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\DB;
+use App\Helpers\AccessLevelHelper;
+
+class MailsController extends Controller
+{
+  public function __construct(Request $request)
+  {
+    $this->request = $request;
+    $this->user_sciper = $this->request->get('user_sciper');
+    $this->user_permissions = $this->request->get('user_permissions');
+  }
+
+  public function mailApplicant()
+  {
+    // TODO: mail to an applicant
+    echo $this->request->input('recipient');
+    echo $this->request->input('from');
+    echo $this->request->input('copy');
+    echo $this->request->input('subject');
+    echo $this->request->input('content');
+
+    // 'EPFL: Votre candidature pour un apprentissage';
+
+    $subject = $this->request->input('subject');
+    $message = $this->request->input('content');
+
+    $headers = array(
+      // 'Content-Type' => 'text/html',
+      // 'charset'=>'UTF8',
+      'From' => 'noreply+test@epfl.ch',
+      'Reply-To' => 'noreply+test@epfl.ch',
+      'X-Mailer' => 'PHP/' . phpversion()
+    );
+    mail($to, $subject, $message, $headers);
+  }
+}
\ No newline at end of file
diff --git a/canapGEST/API/app/Http/Controllers/UsersController.php b/canapGEST/API/app/Http/Controllers/UsersController.php
index 19de5230aaff78e321627d04ede67f25049c9f43..f02a8080c14e7f4b70f8b69d9c68ff2dc92dd772 100644
--- a/canapGEST/API/app/Http/Controllers/UsersController.php
+++ b/canapGEST/API/app/Http/Controllers/UsersController.php
@@ -72,12 +72,14 @@ class UsersController extends Controller
 
   public function getLastConnection ()
   {
+    // TODO: this dont work, must be auth
     $last_connection = DB::table('last_connection')->where('last_connection_sciper', $this->user_sciper)->first();
     return $last_connection ? ["last_connection" => $last_connection] : ["last_connection" => null];
   }
 
   public function setLastConnection ()
   {
+    // TODO: this dont work, must be auth
     $last_connection = DB::table('last_connection')->where('last_connection_sciper', $this->user_sciper)->first();
     if ($last_connection) {
       // Get tmp -> set to date, actual date to tmp
diff --git a/canapGEST/API/app/Http/Middleware/JwtMiddleware.php b/canapGEST/API/app/Http/Middleware/JwtMiddleware.php
index e8055c6c6f3e00b29beb171382f69f0a20e854f9..a20e413b40b352d159c74a4ce819651457a169e0 100644
--- a/canapGEST/API/app/Http/Middleware/JwtMiddleware.php
+++ b/canapGEST/API/app/Http/Middleware/JwtMiddleware.php
@@ -21,11 +21,13 @@ class JwtMiddleware
       $content = JWT::decode($token, env('JWT_SECRET'), ['HS256']);
     } catch (ExpiredException $e) {
       return response()->json([
-        'error' => 'Session expirée'
+        'error' => 'Session expirée',
+        'type' => 'expired'
       ], 400);
     } catch (Exception $e) {
       return response()->json([
-        'error' => 'Error while decoding token'
+        'error' => 'Error while decoding token',
+        'type' => 'error'
       ], 400);
     }
 
diff --git a/canapGEST/API/routes/web.php b/canapGEST/API/routes/web.php
index d32119d9c3041623bdb32925055a3946bde190cf..95a48946dcde89fd427e83255ce06c5cf6f4c334 100644
--- a/canapGEST/API/routes/web.php
+++ b/canapGEST/API/routes/web.php
@@ -49,7 +49,11 @@ $router->group(['middleware' => 'jwt.auth'], function () use ($router) {
 
   // Files
   $router->get('api/file/{id:[0-9]+}', 'FilesController@getFile');
+  $router->get('api/files/applicant/{id:[0-9]+}', 'FilesController@exportApplicantFiles');
 
   // Stats
   $router->get('api/stats/total', 'StatsController@getTotal');
+
+  // Mails
+  $router->post('api/mail/applicant', 'MailsController@mailApplicant');
 });
\ No newline at end of file
diff --git a/canapGEST/Site/src/components/application/applicationTitle.vue b/canapGEST/Site/src/components/application/applicationTitle.vue
index e6f370c741ac6a3eb50c776e503e7a294bd049f5..b02024f3f52291885aa246a28687fafc61ffb420 100644
--- a/canapGEST/Site/src/components/application/applicationTitle.vue
+++ b/canapGEST/Site/src/components/application/applicationTitle.vue
@@ -46,7 +46,7 @@
               <v-icon>get_app</v-icon>
             </v-btn>
           </template>
-          <span>Exporter (JSON)</span>
+          <span>Exporter (Dossier complet)</span>
         </v-tooltip>
       </v-toolbar-items>
     </v-toolbar>
diff --git a/canapGEST/Site/src/components/application/sheets/filesDataSheet.vue b/canapGEST/Site/src/components/application/sheets/filesDataSheet.vue
index d9187d27353e69b96630d699a72796b7da9be114..60298fa9177f2b570752974c5bfcac1045279c86 100644
--- a/canapGEST/Site/src/components/application/sheets/filesDataSheet.vue
+++ b/canapGEST/Site/src/components/application/sheets/filesDataSheet.vue
@@ -44,9 +44,7 @@ export default {
       this.$store.dispatch('moduleApplications/getFile', { id: id, name: name })
     },
     getAllFiles() {
-      this.$store.state.moduleApplications.currentApplication.application_data.files.forEach(file => {
-        this.$store.dispatch('moduleApplications/getFile', { id: file.file_id, name: file.file_name })
-      })
+      this.$store.dispatch('moduleApplications/getAllFiles', { id: this.$store.state.moduleApplications.currentApplication.application_data.personal_data.applicant_id })
     }
   }
 }
diff --git a/canapGEST/Site/src/store/modules/applications/actions.js b/canapGEST/Site/src/store/modules/applications/actions.js
index ee8c797f2e51956a12da0ae58f5bc12cb03c19ca..5fc9e1a2442add969fb84b347cc1aa887ca15293 100644
--- a/canapGEST/Site/src/store/modules/applications/actions.js
+++ b/canapGEST/Site/src/store/modules/applications/actions.js
@@ -100,6 +100,17 @@ export function getFile (context, data) {
     })
 }
 
+export function getAllFiles (context, data) {
+  axios({
+    method: 'get',
+    url: '/files/applicant/' + data.id,
+    responseType: 'blob'
+  })
+    .then(response => {
+      generateBlob(response, data.id + 'export-annexes.zip')
+    })
+}
+
 function getOwnerData (sciper) {
   return axios({
     method: 'get',
@@ -117,7 +128,7 @@ export function exportData (context, data) {
     responseType: 'blob'
   })
     .then(response => {
-      generateBlob(response, 'export' + data.name + '.json')
+      generateBlob(response, 'export' + data.name.replace(/\s/g, '') + '.zip')
     })
 }
 
diff --git a/canapGEST/Site/src/views/ApplicationsView.vue b/canapGEST/Site/src/views/ApplicationsView.vue
index 7d1121a297828f345c508a385448eb545106d3e8..503912762e66b32a8067cd6c6b8ed4a706882f94 100644
--- a/canapGEST/Site/src/views/ApplicationsView.vue
+++ b/canapGEST/Site/src/views/ApplicationsView.vue
@@ -15,7 +15,7 @@
           ></v-select>
           <v-btn round color="primary" @click="updateMultiple">Appliquer</v-btn>
           <v-btn round color="primary" @click="deleteMultiple">Supprimer</v-btn>
-          <v-btn round color="primary" @click="toggleMailDialog()">Contacter</v-btn>
+          <v-btn round color="primary" @click="toggleMailDialog">Contacter</v-btn>
         </div>
       </v-card-title>
       <v-data-table
@@ -29,14 +29,12 @@
       >
         <template v-slot:items="props">
           <span></span>
-          <tr
-            :class="{ isNew: isNew(props.item.fk_status, props.item.applicant_application_date) }"
-          >
-            <td v-if="$store.getters['moduleUser/userIsResponsible']">
+          <tr :class="{ isNew: isNew(props.item.fk_status, props.item.applicant_application_date) }">
+            <td v-if="$store.getters['moduleUser/userIsResponsible']" :class="{ isNew: isNew(props.item.fk_status, props.item.applicant_application_date) }">
               <v-checkbox v-model="props.selected" hide-details color="primary"></v-checkbox>
             </td>
             <td>
-              <v-tooltip bottom class="mr-2">
+              <v-tooltip bottom class="mr-2" >
                 <template v-slot:activator="{ on }">
                   <v-icon big @click="navigateTo(props.item.applicant_id)" v-on="on">pageview</v-icon>
                 </template>
@@ -172,7 +170,7 @@ export default {
         this.updateStatus(item.applicant_id, this.multipleEditor.status)
       })
       setTimeout(() => {
-      this.$store.dispatch('moduleApplications/getApplications')
+        this.$store.dispatch('moduleApplications/getApplications')
       }, 300)
     },
     deleteMultiple () {