diff --git a/VERSIONS_HOTLINE/177511 b/VERSIONS_HOTLINE/177511
new file mode 100644
index 0000000000000000000000000000000000000000..fd9274d3294b0074dd93c6a9c8484015874ed81f
--- /dev/null
+++ b/VERSIONS_HOTLINE/177511
@@ -0,0 +1 @@
+ - correctif #177511 : Administration : Dans le module de gestion des abonnés portail, l'envoi du courriel des abonnés à valider est effectué que lorsqu'il y en a.
\ No newline at end of file
diff --git a/library/Class/Bib/PortalBorrowers.php b/library/Class/Bib/PortalBorrowers.php
index 0ea3c67c7855e26c07c5d0880bb2f859eb3d0cdd..4c04b33b474cc2b8b8266cf8904505260560ce56 100644
--- a/library/Class/Bib/PortalBorrowers.php
+++ b/library/Class/Bib/PortalBorrowers.php
@@ -160,10 +160,13 @@ class Class_Bib_PortalBorrowers {
 
 
   public function renderCsvOn(Zend_View $view) : string {
+    if ( ! $users_to_validate = $this->getUsersToValidate())
+      return '';
+
     return $view
       ->renderCsv((new Class_TableDescription_PortalBorrowersExport('to_validate'))
                   ->setPortalBorrowers($this),
-                  $this->getUsersToValidate(),
+                  $users_to_validate,
                   ',');
   }
 
@@ -191,21 +194,31 @@ class Class_Bib_PortalBorrowers {
                                 Closure $message_callback) : string {
     $recipient = $this->recipientEmail();
     $message = $message_callback($this->getLibelle(), $recipient);
+    $error = '';
+
+    if ($content = $this->renderCsvOn($view))
+      $error = $this->_trySendMail($recipient, $content, $journal);
 
+    $journal->save($this);
+
+    return $error ? $error : $message;
+  }
+
+
+  protected function _trySendMail(string $recipient, string $content, Class_Journal_Type $journal) : string {
+    $message = '';
     try {
       (new ZendAfi_Mail)
         ->setFrom($this->emailFrom())
         ->addTo($recipient)
         ->setSubject($this->emailSubject())
         ->setBodyHtml($this->emailBody())
-        ->attachContent($this->renderCsvOn($view), 'text/csv', $this->exportFileName())
+        ->attachContent($content, 'text/csv', $this->exportFileName())
         ->send();
     } catch(Exception $e) {
       $journal->addError($message = $e->getMessage());
     }
 
-    $journal->save($this);
-
     return $message;
   }
 
diff --git a/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php b/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php
index 50a64d3b10cfa77cb00e976b82e4019439335c18..c38deef38638517bba2c817118163bbe1b5a84ea 100644
--- a/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php
+++ b/tests/application/modules/opac/controllers/AuthControllerWithNanookTest.php
@@ -356,14 +356,17 @@ abstract class AuthControllerWithNanookPostAxelLoginTestCase
   }
 
 
-  public function tearDown(){
+  public function tearDown() {
     parent::tearDown();
     Class_User_Membership::setTimesource(null);
+    Class_Users::setTimesource(null);
   }
 
 
   protected function _prepareMemberships(){
-    Class_User_Membership::setTimesource(new TimeSourceForTest('2022-01-01 08:00:00'));
+    $time = new TimeSourceForTest('2022-01-01 08:00:00');
+    Class_User_Membership::setTimesource($time);
+    Class_Users::setTimesource($time);
     $this->_patron_info = NanookFixtures::axelPatronInfo();
     $this->fixture(Class_Membership::class,
                    ['id' => 1415,
@@ -421,8 +424,10 @@ class AuthControllerWithNanookPostAxelLoginNoMemberships
    * @depends userMembershipShouldHaveBeenCreated
    */
   public function userAxelgetUserMembershipsShouldBeUserMembershipCreated($usermembership) {
-    $this->assertEquals([$usermembership],
-                        Class_Users::find(667)->getUserMemberships());
+    $this->assertEquals($usermembership->getId(),
+                        ($user_memberships = Class_Users::find(667)->getUserMemberships())
+                        ? reset($user_memberships)->getId()
+                        : null);
   }
 }
 
@@ -553,7 +558,9 @@ class AuthControllerWithNanookPostAxelLoginWithRoleLevelModoBibWithoutLabelButEx
 
 
   protected function _prepareMemberships(){
-    Class_User_Membership::setTimesource(new TimeSourceForTest('2022-01-01 08:00:00'));
+    $time = new TimeSourceForTest('2022-01-01 08:00:00');
+    Class_User_Membership::setTimesource($time);
+    Class_Users::setTimesource($time);
     $this->_patron_info = NanookFixtures::axelPatronInfo();
 
     $this->fixture(Class_Membership::class,
diff --git a/tests/application/modules/push/controllers/WebkioskControllerTest.php b/tests/application/modules/push/controllers/WebkioskControllerTest.php
index 49d0d17ed29beb0f9815abf88c1efb052b5dfec4..b72dedf231db0f7f21eb456e1a9df4baff8c391f 100644
--- a/tests/application/modules/push/controllers/WebkioskControllerTest.php
+++ b/tests/application/modules/push/controllers/WebkioskControllerTest.php
@@ -37,11 +37,18 @@ abstract class Push_WebkioskControllerWithSSLTestCase extends AbstractController
     $time = new TimeSourceForTest('2022-11-22');
 
     new Class_Multimedia;
+    Class_Users::setTimeSource($time);
     Class_Multimedia_HashValidator_Md5::setTimeSource($time);
     Class_Multimedia_Connector_GeneratorRendering::setTimeSource($time);
   }
 
 
+  public function tearDown() {
+    Class_Users::setTimeSource(null);
+    return parent::tearDown();
+  }
+
+
   protected function _signDataWithDate(string $data) : string {
     return $this->_signature = (new Class_Multimedia_Connector_Webkiosk)
       ->signWithDate($data, file_get_contents(__DIR__ . '/ssl_private.key'));
@@ -536,4 +543,4 @@ class Push_WebkioskControllerGetIncrementialBorrowersAfterFullTest
     $this->assertEquals('{"data":[{"idabon":"all1","login":"loas","password":"loas42pat","nom":"Loas","prenom":"Ghislain","mail":"loas@mail.fr","dateNaissanceIso8601":"1978\/02\/17","dateFin":"2030-01-01","dateDebut":"2022-01-01"},{"idabon":"all2","login":"ama","password":"ama","nom":"DIOUF","prenom":"Amadou","mail":"diouf@mail.fr","dateNaissanceIso8601":"1980\/02\/17","dateFin":"2030-01-01","dateDebut":"2029-01-01"}],"error":"","date_export":"2022-11-22T00:00:00+01:00","fullImport":false}',
                         $this->_sslUncrypt('data_encrypted'));
   }
-}
\ No newline at end of file
+}
diff --git a/tests/scenarios/PortalBorrowers/PortalBorrowersBatchTest.php b/tests/scenarios/PortalBorrowers/PortalBorrowersBatchTest.php
index a8706d35a25d62b24a9994d1a0813fdc511aea28..cffb11360e326a50169b6f2ad1a0547cbc3ba49d 100644
--- a/tests/scenarios/PortalBorrowers/PortalBorrowersBatchTest.php
+++ b/tests/scenarios/PortalBorrowers/PortalBorrowersBatchTest.php
@@ -73,7 +73,7 @@ class PortalBorrowersBatchFixtures {
   }
 
 
-  public function sentMail() : Zend_Mail {
+  public function sentMail() : ?Zend_Mail {
     return $this->_transport->sent_mail;
   }
 
@@ -462,3 +462,46 @@ class PortalBorrowersNotLoadingTest extends PHPUnit_Framework_TestCase {
     $this->assertNotNull(new Class_Batch_PortalBorrowersEmailing);
   }
 }
+
+
+
+
+class PortalBorrowersBatchEnabledRunWithEmptyCSVTest extends PortalBorrowersActivatedTestCase {
+
+  protected ?ZendAfi_Mail $_sent_mail;
+  protected PortalBorrowersBatchFixtures $_fixtures;
+
+
+  public function setUp() {
+    parent::setUp();
+
+    $this->_fixtures = (new PortalBorrowersBatchFixtures)->setUp();
+
+    Class_Users::find(789)->delete();
+
+    $this->dispatch('/admin/batch/run/id/PORTAL_BORROWERS_EMAILING');
+    $this->_sent_mail = $this->_fixtures->sentMail();
+  }
+
+
+  public function tearDown() {
+    $this->_fixtures->tearDown();
+  }
+
+
+  /**
+   * @test
+   * @see PortalBorrowersAdminTest covering other email details
+   */
+  public function shouldNotHaveSentMailToWebmasterNyons() {
+    $this->assertNull($this->_sent_mail);
+  }
+
+
+  /** @test */
+  public function shouldCreateBatchEmailJournal() {
+    $journal = Class_Journal::lastOf(Class_Journal_PortalBorrowersMailType::MY_TYPE . '_1');
+    $this->assertEquals('PORTAL_BORROWERS_BATCH',
+                        $journal->getDetail(Class_Journal_PortalBorrowersMailType::MODE)->getValue());
+  }
+}