From: Louis Jeckel Date: Wed, 16 Sep 2020 11:41:06 +0000 (+0200) Subject: add email validation X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=5176787fc7240dde85c7ad47ff8224580fc637a4;p=psq.git add email validation --- diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml index 03d9549..ca39155 100644 --- a/.idea/inspectionProfiles/Project_Default.xml +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -2,5 +2,128 @@ \ No newline at end of file diff --git a/app/MailgunValidation.php b/app/MailgunValidation.php new file mode 100644 index 0000000..3e872f0 --- /dev/null +++ b/app/MailgunValidation.php @@ -0,0 +1,131 @@ + '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 index 0000000..c82905f --- /dev/null +++ b/app/Nova/Actions/ValidateAddress.php @@ -0,0 +1,37 @@ +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 index 0000000..c49dc47 --- /dev/null +++ b/app/Nova/Lenses/NonDeliverableAddresses.php @@ -0,0 +1,99 @@ +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'; + } +} diff --git a/app/Nova/User.php b/app/Nova/User.php index b7991de..5cb414a 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -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, ]; } } diff --git a/app/User.php b/app/User.php index 7b9c524..0fe83fc 100644 --- a/app/User.php +++ b/app/User.php @@ -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 index 0000000..6f684cb --- /dev/null +++ b/database/migrations/2020_09_16_104354_create_validations_table.php @@ -0,0 +1,36 @@ +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'); + } +}