From 146ec8facb9cbdf4ff4711cddb22c246aea62b7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Jaussoin?= Date: Thu, 9 Oct 2025 15:06:30 +0200 Subject: [PATCH] Fix FLEXIAPI-366 Send the voicemails by email --- cron/flexiapi.cron | 1 + flexiapi/app/AccountFile.php | 7 +++- .../Accounts/SendVoicemailsEmails.php | 40 +++++++++++++++++++ flexiapi/app/Mail/ExpiringSpace.php | 1 - flexiapi/app/Mail/NewsletterRegistration.php | 1 - flexiapi/app/Mail/Provisioning.php | 1 - flexiapi/app/Mail/RecoverByCode.php | 1 - flexiapi/app/Mail/ResetPassword.php | 2 - flexiapi/app/Mail/Voicemail.php | 40 +++++++++++++++++++ ...0_20_093414_create_account_files_table.php | 3 ++ flexiapi/lang/fr.json | 2 + flexiapi/phpmd.xml | 1 - .../resources/views/mails/voicemail.blade.php | 14 +++++++ flexiapi/routes/console.php | 20 +++------- flexisip-account-manager.spec | 5 +++ 15 files changed, 115 insertions(+), 24 deletions(-) create mode 100644 cron/flexiapi.cron create mode 100644 flexiapi/app/Console/Commands/Accounts/SendVoicemailsEmails.php create mode 100644 flexiapi/app/Mail/Voicemail.php create mode 100644 flexiapi/resources/views/mails/voicemail.blade.php diff --git a/cron/flexiapi.cron b/cron/flexiapi.cron new file mode 100644 index 0000000..1d1f40e --- /dev/null +++ b/cron/flexiapi.cron @@ -0,0 +1 @@ +* * * * * cd /opt/belledonne-communications/share/flexisip-account-manager/flexiapi/ && php artisan schedule:run >> /dev/null 2>&1 \ No newline at end of file diff --git a/flexiapi/app/AccountFile.php b/flexiapi/app/AccountFile.php index 404f28f..25ec6e9 100644 --- a/flexiapi/app/AccountFile.php +++ b/flexiapi/app/AccountFile.php @@ -12,8 +12,11 @@ class AccountFile extends Model public const VOICEMAIL_CONTENTTYPES = ['audio/opus', 'audio/wav']; public const FILES_PATH = 'files'; - protected $hidden = ['account_id', 'updated_at']; + protected $hidden = ['account_id', 'updated_at', 'sending_by_mail_at', 'sent_by_mail_at', 'sending_by_mail_tryouts']; protected $appends = ['download_url']; + protected $casts = [ + 'uploaded_at' => 'datetime', + ]; protected static function booted() { @@ -24,7 +27,7 @@ class AccountFile extends Model public function account() { - return $this->belongsTo(Account::class); + return $this->belongsTo(Account::class)->withoutGlobalScopes(); } public function getMaxUploadSizeAttribute(): ?int diff --git a/flexiapi/app/Console/Commands/Accounts/SendVoicemailsEmails.php b/flexiapi/app/Console/Commands/Accounts/SendVoicemailsEmails.php new file mode 100644 index 0000000..a5ba5ad --- /dev/null +++ b/flexiapi/app/Console/Commands/Accounts/SendVoicemailsEmails.php @@ -0,0 +1,40 @@ +whereNull('sent_by_mail_at') + ->where('sending_by_mail_tryouts', '<', is_int($this->option('tryout')) + ? $this->option('tryout') + : 3) + ->get(); + + foreach ($voicemails as $voicemail) { + $voicemail->sending_by_mail_at = Carbon::now(); + $voicemail->save(); + + if (Mail::to(users: $voicemail->account)->send(new Voicemail($voicemail))) { + $voicemail->sent_by_mail_at = Carbon::now(); + $this->info('Voicemail sent to ' . $voicemail->account->identifier); + } else { + $voicemail->sending_by_mail_tryouts++; + $this->info('Error sending voicemail to ' . $voicemail->account->identifier); + } + + $voicemail->save(); + } + } +} diff --git a/flexiapi/app/Mail/ExpiringSpace.php b/flexiapi/app/Mail/ExpiringSpace.php index b540810..c315a54 100644 --- a/flexiapi/app/Mail/ExpiringSpace.php +++ b/flexiapi/app/Mail/ExpiringSpace.php @@ -5,7 +5,6 @@ namespace App\Mail; use App\Space; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; diff --git a/flexiapi/app/Mail/NewsletterRegistration.php b/flexiapi/app/Mail/NewsletterRegistration.php index bcd590d..b55c8d7 100644 --- a/flexiapi/app/Mail/NewsletterRegistration.php +++ b/flexiapi/app/Mail/NewsletterRegistration.php @@ -22,7 +22,6 @@ namespace App\Mail; use App\Account; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; diff --git a/flexiapi/app/Mail/Provisioning.php b/flexiapi/app/Mail/Provisioning.php index 097dd67..10995ef 100644 --- a/flexiapi/app/Mail/Provisioning.php +++ b/flexiapi/app/Mail/Provisioning.php @@ -22,7 +22,6 @@ namespace App\Mail; use App\Account; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; diff --git a/flexiapi/app/Mail/RecoverByCode.php b/flexiapi/app/Mail/RecoverByCode.php index 16f58ca..5aa0354 100644 --- a/flexiapi/app/Mail/RecoverByCode.php +++ b/flexiapi/app/Mail/RecoverByCode.php @@ -22,7 +22,6 @@ namespace App\Mail; use App\Account; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; diff --git a/flexiapi/app/Mail/ResetPassword.php b/flexiapi/app/Mail/ResetPassword.php index 4abc43a..e045bd7 100644 --- a/flexiapi/app/Mail/ResetPassword.php +++ b/flexiapi/app/Mail/ResetPassword.php @@ -20,10 +20,8 @@ namespace App\Mail; use App\Account; -use App\ResetPasswordEmailToken; use Illuminate\Bus\Queueable; -use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; diff --git a/flexiapi/app/Mail/Voicemail.php b/flexiapi/app/Mail/Voicemail.php new file mode 100644 index 0000000..2a0e71f --- /dev/null +++ b/flexiapi/app/Mail/Voicemail.php @@ -0,0 +1,40 @@ +accountFile->account->space->name . + ': ' . + __('New voice message from :sipfrom', ['sipfrom' => $this->accountFile->sip_from]), + ); + } + + public function content(): Content + { + return new Content( + markdown: 'mails.voicemail', + ); + } + + public function attachments(): array + { + return []; + } +} diff --git a/flexiapi/database/migrations/2025_10_20_093414_create_account_files_table.php b/flexiapi/database/migrations/2025_10_20_093414_create_account_files_table.php index 6be05d2..cedde59 100644 --- a/flexiapi/database/migrations/2025_10_20_093414_create_account_files_table.php +++ b/flexiapi/database/migrations/2025_10_20_093414_create_account_files_table.php @@ -18,6 +18,9 @@ return new class extends Migration $table->string('content_type')->index(); $table->text('sip_from')->nullable(); $table->dateTime('uploaded_at')->nullable(); + $table->dateTime('sending_by_mail_at')->nullable(); + $table->integer('sending_by_mail_tryouts')->default(0); + $table->dateTime('sent_by_mail_at')->nullable(); $table->timestamps(); }); } diff --git a/flexiapi/lang/fr.json b/flexiapi/lang/fr.json index 47a70d5..c390f6f 100644 --- a/flexiapi/lang/fr.json +++ b/flexiapi/lang/fr.json @@ -145,6 +145,7 @@ "New newsletter subscription": "Nouvelle inscription à votre newsletter", "New Space": "Nouvel Espace", "New user": "Nouvel utilisateur", + "New voice message from :sipfrom": "Nouveau message vocal de :sipfrom", "Newsletter registration email address": "Addresse email d'inscription à la liste de diffusion", "Next": "Suivant", "No account yet?": "Pas encore de compte ?", @@ -170,6 +171,7 @@ "QR Code scanning": "Scan de QR Code", "Realm": "Royaume", "Recover your account using your email": "Récupérer votre compte avec votre email", + "Recorded at": "Enregistré le", "Register": "Inscription", "Registrar": "Registrar", "Registration confirmed": "Confirmation de l'inscription", diff --git a/flexiapi/phpmd.xml b/flexiapi/phpmd.xml index 953c29e..0b70f75 100644 --- a/flexiapi/phpmd.xml +++ b/flexiapi/phpmd.xml @@ -10,7 +10,6 @@ The Clean Code ruleset contains rules that enforce a clean code base. This includes rules from SOLID and object calisthenics. - diff --git a/flexiapi/resources/views/mails/voicemail.blade.php b/flexiapi/resources/views/mails/voicemail.blade.php new file mode 100644 index 0000000..b727444 --- /dev/null +++ b/flexiapi/resources/views/mails/voicemail.blade.php @@ -0,0 +1,14 @@ +@extends('mails.layout') + +@section('content') +# {{ __('New voice message from :sipfrom', ['sipfrom' => $accountFile->sip_from]) }} + +{{ __('New voice message') }} + +{{ __('From') }}: {{ $accountFile->sip_from }} + +{{ __('To') }}: {{ $accountFile->account->identifier }} + +{{ __('Recorded at') }}: {{ $accountFile->created_at->toDateTimeString() }} + +@endsection diff --git a/flexiapi/routes/console.php b/flexiapi/routes/console.php index 75dd0cd..e91e885 100644 --- a/flexiapi/routes/console.php +++ b/flexiapi/routes/console.php @@ -1,18 +1,8 @@ comment(Inspiring::quote()); -})->describe('Display an inspiring quote'); +Schedule::command(ClearFiles::class, [7, '--apply'])->daily(); +Schedule::command(SendVoicemailsEmails::class)->everyMinute(); diff --git a/flexisip-account-manager.spec b/flexisip-account-manager.spec index b3ae4fa..a77dd99 100644 --- a/flexisip-account-manager.spec +++ b/flexisip-account-manager.spec @@ -54,6 +54,7 @@ cp flexiapi/composer.json "$RPM_BUILD_ROOT%{opt_dir}/flexiapi" cp README* "$RPM_BUILD_ROOT%{opt_dir}/" cp INSTALL* "$RPM_BUILD_ROOT%{opt_dir}/" mkdir -p $RPM_BUILD_ROOT/etc/cron.daily +mkdir -p $RPM_BUILD_ROOT/etc/cron.d mkdir -p $RPM_BUILD_ROOT%{apache_conf_path} cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/" @@ -66,6 +67,9 @@ cp httpd/flexisip-account-manager.conf "$RPM_BUILD_ROOT%{apache_conf_path}/" chmod +x "$RPM_BUILD_ROOT/etc/cron.daily/flexiapi.redhat" %endif +cp cron/flexiapi.cron "$RPM_BUILD_ROOT/etc/cron.d/" +chmod +x "$RPM_BUILD_ROOT/etc/cron.d/flexiapi.cron" + # POST INSTALLATION %posttrans @@ -161,6 +165,7 @@ fi %exclude %{opt_dir}/flexiapi/storage/ +%config /etc/cron.d/flexiapi.cron %config(noreplace) %{apache_conf_path}/flexisip-account-manager.conf %if %{with deb} %config(noreplace) /etc/cron.daily/flexiapi.debian