]> _ Git - psq.git/commitdiff
add email validation
authorLouis Jeckel <louis.jeckel@outlook.cm>
Wed, 16 Sep 2020 11:41:06 +0000 (13:41 +0200)
committerLouis Jeckel <louis.jeckel@outlook.cm>
Wed, 16 Sep 2020 11:41:06 +0000 (13:41 +0200)
.idea/inspectionProfiles/Project_Default.xml
app/MailgunValidation.php [new file with mode: 0644]
app/Nova/Actions/ValidateAddress.php [new file with mode: 0644]
app/Nova/Lenses/NonDeliverableAddresses.php [new file with mode: 0644]
app/Nova/User.php
app/User.php
database/migrations/2020_09_16_104354_create_validations_table.php [new file with mode: 0644]

index 03d9549ea8e4ada36fb3ecbc30fef08175b7d728..ca391558b584812cda2420d41910b2605efba9db 100644 (file)
@@ -2,5 +2,128 @@
   <profile version="1.0">
     <option name="myName" value="Project Default" />
     <inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
+    <inspection_tool class="ForgottenDebugOutputInspection" enabled="true" level="ERROR" enabled_by_default="true">
+      <option name="configuration">
+        <list>
+          <option value="\Codeception\Util\Debug::debug" />
+          <option value="\Codeception\Util\Debug::pause" />
+          <option value="\Doctrine\Common\Util\Debug::dump" />
+          <option value="\Doctrine\Common\Util\Debug::export" />
+          <option value="\Illuminate\Support\Debug\Dumper::dump" />
+          <option value="\Symfony\Component\Debug\Debug::enable" />
+          <option value="\Symfony\Component\Debug\DebugClassLoader::enable" />
+          <option value="\Symfony\Component\Debug\ErrorHandler::register" />
+          <option value="\Symfony\Component\Debug\ExceptionHandler::register" />
+          <option value="\TYPO3\CMS\Core\Utility\DebugUtility::debug" />
+          <option value="\Zend\Debug\Debug::dump" />
+          <option value="\Zend\Di\Display\Console::export" />
+          <option value="dd" />
+          <option value="debug_print_backtrace" />
+          <option value="debug_zval_dump" />
+          <option value="dpm" />
+          <option value="dpq" />
+          <option value="dsm" />
+          <option value="dump" />
+          <option value="dvm" />
+          <option value="error_log" />
+          <option value="kpr" />
+          <option value="phpinfo" />
+          <option value="print_r" />
+          <option value="var_dump" />
+          <option value="var_export" />
+          <option value="wp_die" />
+          <option value="xdebug_break" />
+          <option value="xdebug_call_class" />
+          <option value="xdebug_call_file" />
+          <option value="xdebug_call_function" />
+          <option value="xdebug_call_line" />
+          <option value="xdebug_code_coverage_started" />
+          <option value="xdebug_debug_zval" />
+          <option value="xdebug_debug_zval_stdout" />
+          <option value="xdebug_dump_superglobals" />
+          <option value="xdebug_enable" />
+          <option value="xdebug_get_code_coverage" />
+          <option value="xdebug_get_collected_errors" />
+          <option value="xdebug_get_declared_vars" />
+          <option value="xdebug_get_function_stack" />
+          <option value="xdebug_get_headers" />
+          <option value="xdebug_get_monitored_functions" />
+          <option value="xdebug_get_profiler_filename" />
+          <option value="xdebug_get_stack_depth" />
+          <option value="xdebug_get_tracefile_name" />
+          <option value="xdebug_is_enabled" />
+          <option value="xdebug_memory_usage" />
+          <option value="xdebug_peak_memory_usage" />
+          <option value="xdebug_print_function_stack" />
+          <option value="xdebug_start_code_coverage" />
+          <option value="xdebug_start_error_collection" />
+          <option value="xdebug_start_function_monitor" />
+          <option value="xdebug_start_trace" />
+          <option value="xdebug_stop_code_coverage" />
+          <option value="xdebug_stop_error_collection" />
+          <option value="xdebug_stop_function_monitor" />
+          <option value="xdebug_stop_trace" />
+          <option value="xdebug_time_index" />
+          <option value="xdebug_var_dump" />
+        </list>
+      </option>
+      <option name="migratedIntoUserSpace" value="true" />
+    </inspection_tool>
+    <inspection_tool class="PhpComposerExtensionStubsInspection" enabled="false" level="WARNING" enabled_by_default="false" />
+    <inspection_tool class="SecurityAdvisoriesInspection" enabled="true" level="WARNING" enabled_by_default="true">
+      <option name="optionConfiguration">
+        <list>
+          <option value="barryvdh/laravel-debugbar" />
+          <option value="behat/behat" />
+          <option value="brianium/paratest" />
+          <option value="codeception/codeception" />
+          <option value="codedungeon/phpunit-result-printer" />
+          <option value="composer/composer" />
+          <option value="doctrine/coding-standard" />
+          <option value="filp/whoops" />
+          <option value="friendsofphp/php-cs-fixer" />
+          <option value="humbug/humbug" />
+          <option value="infection/infection" />
+          <option value="jakub-onderka/php-parallel-lint" />
+          <option value="johnkary/phpunit-speedtrap" />
+          <option value="kalessil/production-dependencies-guard" />
+          <option value="mikey179/vfsStream" />
+          <option value="mockery/mockery" />
+          <option value="mybuilder/phpunit-accelerator" />
+          <option value="orchestra/testbench" />
+          <option value="pdepend/pdepend" />
+          <option value="phan/phan" />
+          <option value="phing/phing" />
+          <option value="phpcompatibility/php-compatibility" />
+          <option value="phpmd/phpmd" />
+          <option value="phpro/grumphp" />
+          <option value="phpspec/phpspec" />
+          <option value="phpspec/prophecy" />
+          <option value="phpstan/phpstan" />
+          <option value="phpunit/phpunit" />
+          <option value="povils/phpmnd" />
+          <option value="roave/security-advisories" />
+          <option value="satooshi/php-coveralls" />
+          <option value="sebastian/phpcpd" />
+          <option value="slevomat/coding-standard" />
+          <option value="spatie/phpunit-watcher" />
+          <option value="squizlabs/php_codesniffer" />
+          <option value="sstalle/php7cc" />
+          <option value="symfony/debug" />
+          <option value="symfony/maker-bundle" />
+          <option value="symfony/phpunit-bridge" />
+          <option value="symfony/var-dumper" />
+          <option value="vimeo/psalm" />
+          <option value="wimg/php-compatibility" />
+          <option value="wp-coding-standards/wpcs" />
+          <option value="yiisoft/yii2-coding-standards" />
+          <option value="yiisoft/yii2-debug" />
+          <option value="yiisoft/yii2-gii" />
+          <option value="zendframework/zend-coding-standard" />
+          <option value="zendframework/zend-debug" />
+          <option value="zendframework/zend-test" />
+        </list>
+      </option>
+    </inspection_tool>
   </profile>
 </component>
\ No newline at end of file
diff --git a/app/MailgunValidation.php b/app/MailgunValidation.php
new file mode 100644 (file)
index 0000000..3e872f0
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+
+namespace App;
+
+use Illuminate\Database\Eloquent\Model;
+use Illuminate\Database\Eloquent\Relations\BelongsTo;
+use Illuminate\Support\Arr;
+use Mailgun\Mailgun;
+
+/**
+ * Class MailgunValidation
+ * @package App
+ * @property string $email
+ * @property bool|null $deliverable
+ * @property string $risk
+ * @property array $reason
+ */
+class MailgunValidation extends Model
+{
+    protected $guarded = [];
+
+    protected $casts = [
+        'reason' => 'array',
+        'deliverable' => 'boolean'
+    ];
+
+    public const RISKS = [
+        'high' => [
+            'badge' => 'danger',
+            'label' => 'Elevé'
+        ],
+        'medium' => [
+            'badge' => 'warning',
+            'label' => 'Moyen'
+        ],
+        'low' => [
+            'badge' => 'success',
+            'label' => 'Bas'
+        ],
+    ];
+
+    public const REASONS = [
+        'unknown_provider' => "Provider MX inconnu",
+        'no_mx' => "Aucun champ MX trouvé",
+        'high_risk_domain' => "Domain à haut risque",
+        'subdomain_mailer' => "Sous domaine risqué",
+        'immature_domain' => "Domaine trop récent",
+        'tld_risk' => "TLD risqué",
+        'mailbox_does_not_exist' => "Boite mail inexistante",
+        'mailbox_is_disposable_address' => "Boite mail jetable",
+        'mailbox_is_role_address' => "BOite mail de rôle",
+    ];
+
+
+    /**
+     * @return BelongsTo
+     */
+    public function user(): BelongsTo
+    {
+        return $this->belongsTo(User::class, 'email', 'email');
+    }
+
+    /**
+     * @return array
+     * Returns full reasons
+     */
+    public function fullReasonsArray(): array
+    {
+        return array_map(
+            fn($reason) => Arr::get(self::REASONS, $reason, 'Inconnu'),
+            $this->reason
+        );
+    }
+
+    /**
+     * @return string
+     * Returns reasons list
+     */
+    public function reasonsString(): string
+    {
+        return implode($this->fullReasonsArray());
+    }
+
+
+    /**
+     * @param string $address
+     * @param bool $force
+     * @return MailgunValidation
+     */
+    public static function validate(string $address, $force = false)
+    {
+
+        if(!$force && $validation = self::query()->where('email', $address)->first()) {
+            return $validation;
+        }
+
+        $params = array(
+            "address" => $address
+        );
+        $ch = curl_init();
+
+        curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
+        curl_setopt($ch, CURLOPT_USERPWD, 'api:'.config('mail.mailgun.api_key'));
+        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+
+        curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
+        curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
+        curl_setopt($ch, CURLOPT_URL, 'https://api.mailgun.net/v4/address/validate');
+        $data = curl_exec($ch);
+        curl_close($ch);
+
+        $data = json_decode($data, false);
+
+        $deliverable = $data->result === null ?
+            null :
+            ($data->result === 'deliverable');
+
+        /** @var MailgunValidation $model */
+        $model = self::query()
+            ->create([
+                'email' => $data->address,
+                'deliverable' => $deliverable,
+                'risk' => $data->risk,
+                'reason' => $data->reason
+            ]);
+
+        return $model;
+
+    }
+
+}
diff --git a/app/Nova/Actions/ValidateAddress.php b/app/Nova/Actions/ValidateAddress.php
new file mode 100644 (file)
index 0000000..c82905f
--- /dev/null
@@ -0,0 +1,37 @@
+<?php
+
+namespace App\Nova\Actions;
+
+use Illuminate\Bus\Queueable;
+use Illuminate\Contracts\Queue\ShouldQueue;
+use Illuminate\Queue\InteractsWithQueue;
+use Illuminate\Support\Collection;
+use Laravel\Nova\Actions\Action;
+use Laravel\Nova\Fields\ActionFields;
+
+class ValidateAddress extends Action implements ShouldQueue
+{
+    use InteractsWithQueue, Queueable;
+
+    /**
+     * Perform the action on the given models.
+     *
+     * @param  \Laravel\Nova\Fields\ActionFields  $fields
+     * @param  \Illuminate\Support\Collection  $models
+     * @return mixed
+     */
+    public function handle(ActionFields $fields, Collection $models)
+    {
+        $models->map->validate();
+    }
+
+    /**
+     * Get the fields available on the action.
+     *
+     * @return array
+     */
+    public function fields()
+    {
+        return [];
+    }
+}
diff --git a/app/Nova/Lenses/NonDeliverableAddresses.php b/app/Nova/Lenses/NonDeliverableAddresses.php
new file mode 100644 (file)
index 0000000..c49dc47
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+
+namespace App\Nova\Lenses;
+
+use Illuminate\Database\Eloquent\Builder;
+use Illuminate\Http\Request;
+use Laravel\Nova\Fields\Boolean;
+use Laravel\Nova\Fields\ID;
+use Laravel\Nova\Fields\Line;
+use Laravel\Nova\Fields\Stack;
+use Laravel\Nova\Fields\Text;
+use Laravel\Nova\Http\Requests\LensRequest;
+use Laravel\Nova\Lenses\Lens;
+
+class NonDeliverableAddresses extends Lens
+{
+    /**
+     * Get the query builder / paginator for the lens.
+     *
+     * @param  \Laravel\Nova\Http\Requests\LensRequest  $request
+     * @param  \Illuminate\Database\Eloquent\Builder  $query
+     * @return mixed
+     */
+    public static function query(LensRequest $request, $query)
+    {
+        return $request->withOrdering($request->withFilters(
+            $query->with('mailgunValidation')
+            ->whereHas('mailgunValidation', function(Builder $builder) {
+                $builder->where('deliverable', 0);
+            })
+        ));
+    }
+
+    /**
+     * Get the fields available to the lens.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array
+     */
+    public function fields(Request $request)
+    {
+        return [
+//            Stack::make('Utilisateur', [
+//                Line::make('first_name')->asHeading(),
+//                Line::make('Email')->asBase(),
+//            ]),
+            Text::make('Name'),
+            Text::make('Email'),
+            Text::make('Risque', fn() => $this->mailgunValidation->risk),
+            Text::make('Raison', fn()  => $this->mailgunValidation->reasonsString()),
+
+
+
+        ];
+    }
+
+    /**
+     * Get the cards available on the lens.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array
+     */
+    public function cards(Request $request)
+    {
+        return [];
+    }
+
+    /**
+     * Get the filters available for the lens.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array
+     */
+    public function filters(Request $request)
+    {
+        return [];
+    }
+
+    /**
+     * Get the actions available on the lens.
+     *
+     * @param  \Illuminate\Http\Request  $request
+     * @return array
+     */
+    public function actions(Request $request)
+    {
+        return parent::actions($request);
+    }
+
+    /**
+     * Get the URI key for the lens.
+     *
+     * @return string
+     */
+    public function uriKey()
+    {
+        return 'non-deliverable-addresses';
+    }
+}
index b7991de99ea98b5120cb217789d4c927f163ca39..5cb414a5ddff93b0e8d3d7ec0d200ac30e5a5856 100644 (file)
@@ -5,9 +5,11 @@ namespace App\Nova;
 use App\Nova\Actions\ImportUsers;
 use App\Nova\Actions\SendNotification;
 use App\Nova\Actions\StartTrial;
+use App\Nova\Actions\ValidateAddress;
 use App\Nova\Actions\VerifyEmail;
 use App\Nova\Lenses\FailedMailgun;
 use App\Nova\Lenses\MailgunStatus;
+use App\Nova\Lenses\NonDeliverableAddresses;
 use App\Nova\Metrics\RegistrationCompletePartition;
 use App\Nova\Metrics\SubscribedUsers;
 use App\Nova\Metrics\TotalUsers;
@@ -154,7 +156,8 @@ class User extends Resource
     {
         return [
             new MailgunStatus,
-            new FailedMailgun
+            new FailedMailgun,
+            new NonDeliverableAddresses
         ];
     }
 
@@ -171,6 +174,7 @@ class User extends Resource
             new SendNotification,
             new StartTrial,
             new VerifyEmail,
+            new ValidateAddress,
         ];
     }
 }
index 7b9c5240153a14c0337ad0aac2964e718c371923..0fe83fcbe846936d78b11af7819ccbe288a21213 100644 (file)
@@ -210,6 +210,14 @@ class User extends Authenticatable implements MustVerifyEmail
             ->orderByDesc('id');
     }
 
+    /**
+     * @return HasOne
+     */
+    public function mailgunValidation()
+    {
+        return $this->hasOne(MailgunValidation::class, 'email', 'email');
+    }
+
 
 
 
@@ -299,6 +307,14 @@ class User extends Authenticatable implements MustVerifyEmail
     }
 
 
+    /**
+     * @return MailgunValidation
+     */
+    public function validate()
+    {
+        return MailgunValidation::validate($this->email);
+    }
+
 
     /**
      * SCOPES
diff --git a/database/migrations/2020_09_16_104354_create_validations_table.php b/database/migrations/2020_09_16_104354_create_validations_table.php
new file mode 100644 (file)
index 0000000..6f684cb
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class CreateValidationsTable extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::create('mailgun_validations', function (Blueprint $table) {
+            $table->id();
+            $table->string('email');
+            $table->boolean('deliverable')->nullable();
+            $table->string('risk')->nullable();
+            $table->json('reason');
+            $table->timestamps();
+
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::dropIfExists('mailgun_validations');
+    }
+}