<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
--- /dev/null
+<?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;
+
+ }
+
+}
--- /dev/null
+<?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 [];
+ }
+}
--- /dev/null
+<?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';
+ }
+}
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;
{
return [
new MailgunStatus,
- new FailedMailgun
+ new FailedMailgun,
+ new NonDeliverableAddresses
];
}
new SendNotification,
new StartTrial,
new VerifyEmail,
+ new ValidateAddress,
];
}
}
->orderByDesc('id');
}
+ /**
+ * @return HasOne
+ */
+ public function mailgunValidation()
+ {
+ return $this->hasOne(MailgunValidation::class, 'email', 'email');
+ }
+
}
+ /**
+ * @return MailgunValidation
+ */
+ public function validate()
+ {
+ return MailgunValidation::validate($this->email);
+ }
+
/**
* SCOPES
--- /dev/null
+<?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');
+ }
+}