Merge pull request #9074 from turbo124/v5-develop

Nordigen / GoCardless updates.
This commit is contained in:
David Bomba 2023-12-27 14:46:28 +11:00 committed by GitHub
commit 575adf88e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 690 additions and 414 deletions

View File

@ -66,21 +66,44 @@ class UserFilters extends QueryFilters
*/ */
public function entityFilter() public function entityFilter()
{ {
return $this->builder->whereHas('company_users', function ($q) {
$q->where('company_id', '=', auth()->user()->company()->id); /** @var \App\Models\User $user */
$user = auth()->user();
return $this->builder->whereHas('company_users', function ($q) use ($user){
$q->where('company_id', '=', $user->company()->id);
}); });
} }
/**
* Hides owner users from the list.
*
* @return Builder
*/
public function hideOwnerUsers(): Builder
{
/** @var \App\Models\User $user */
$user = auth()->user();
return $this->builder->whereHas('company_users', function ($q) use ($user) {
$q->where('company_id', '=', $user->company()->id)->where('is_owner', false);
});
}
/** /**
* Filters users that have been removed from the * Filters users that have been removed from the
* company, but not deleted from the system. * company, but not deleted from the system.
* *
* @return void * @return Builder
*/ */
public function hideRemovedUsers() public function hideRemovedUsers(): Builder
{ {
return $this->builder->whereHas('company_users', function ($q) { /** @var \App\Models\User $user */
$q->where('company_id', '=', auth()->user()->company()->id)->whereNull('deleted_at'); $user = auth()->user();
return $this->builder->whereHas('company_users', function ($q) use ($user) {
$q->where('company_id', '=', $user->company()->id)->whereNull('deleted_at');
}); });
} }
@ -98,12 +121,21 @@ class UserFilters extends QueryFilters
return $this->builder; return $this->builder;
} }
/** @var \App\Models\User $user */
$user = auth()->user();
return $this->builder return $this->builder
->orWhere($this->with_property, $value) ->orWhere($this->with_property, $value)
->orderByRaw("{$this->with_property} = ? DESC", [$value]) ->orderByRaw("{$this->with_property} = ? DESC", [$value])
->where('account_id', auth()->user()->account_id); ->where('account_id', $user->account_id);
} }
/**
* Returns users with permissions to send emails via OAuth
*
* @param string $value
* @return Builder
*/
public function sending_users(string $value = ''): Builder public function sending_users(string $value = ''): Builder
{ {
if (strlen($value) == 0 || $value != 'true') { if (strlen($value) == 0 || $value != 'true') {

View File

@ -39,7 +39,7 @@ class Nordigen
$this->client = new \Nordigen\NordigenPHP\API\NordigenClient(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key')); $this->client = new \Nordigen\NordigenPHP\API\NordigenClient(config('ninja.nordigen.secret_id'), config('ninja.nordigen.secret_key'));
$this->client->createAccessToken(); // access_token is valid 24h -> so we dont have to implement a refresh-cycle $this->client->createAccessToken();
} }
// metadata-section for frontend // metadata-section for frontend
@ -52,12 +52,12 @@ class Nordigen
} }
// requisition-section // requisition-section
public function createRequisition(string $redirect, string $initutionId, string $reference) public function createRequisition(string $redirect, string $initutionId, string $reference, string $userLanguage)
{ {
if ($this->test_mode && $initutionId != $this->sandbox_institutionId) if ($this->test_mode && $initutionId != $this->sandbox_institutionId)
throw new \Exception('invalid institutionId while in test-mode'); throw new \Exception('invalid institutionId while in test-mode');
return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference); return $this->client->requisition->createRequisition($redirect, $initutionId, null, $reference, $userLanguage);
} }
public function getRequisition(string $requisitionId) public function getRequisition(string $requisitionId)
@ -85,6 +85,7 @@ class Nordigen
$it = new AccountTransformer(); $it = new AccountTransformer();
return $it->transform($out); return $it->transform($out);
} catch (\Exception $e) { } catch (\Exception $e) {
if (strpos($e->getMessage(), "Invalid Account ID") !== false) if (strpos($e->getMessage(), "Invalid Account ID") !== false)
return false; return false;
@ -92,8 +93,14 @@ class Nordigen
throw $e; throw $e;
} }
} }
public function isAccountActive(string $account_id) /**
* isAccountActive
*
* @param string $account_id
* @return bool
*/
public function isAccountActive(string $account_id): bool
{ {
try { try {
$account = $this->client->account($account_id)->getAccountMetaData(); $account = $this->client->account($account_id)->getAccountMetaData();
@ -112,11 +119,15 @@ class Nordigen
} }
} }
/** /**
* this method returns booked transactions from the bank_account, pending transactions are not part of the result * getTransactions
* @todo @turbo124 should we include pending transactions within the integration-process and mark them with a specific category?! *
* @param string $accountId
* @param string $dateFrom
* @return array
*/ */
public function getTransactions(string $accountId, string $dateFrom = null) public function getTransactions(string $accountId, string $dateFrom = null): array
{ {
$transactionResponse = $this->client->account($accountId)->getAccountTransactions($dateFrom); $transactionResponse = $this->client->account($accountId)->getAccountTransactions($dateFrom);

View File

@ -113,8 +113,8 @@ class TransactionTransformer implements BankRevenueInterface
'transaction_id' => $transaction["transactionId"], 'transaction_id' => $transaction["transactionId"],
'amount' => abs((int) $transaction["transactionAmount"]["amount"]), 'amount' => abs((int) $transaction["transactionAmount"]["amount"]),
'currency_id' => $this->convertCurrency($transaction["transactionAmount"]["currency"]), 'currency_id' => $this->convertCurrency($transaction["transactionAmount"]["currency"]),
'category_id' => null, // nordigen has no categories 'category_id' => null,
'category_type' => array_key_exists('additionalInformation', $transaction) ? $transaction["additionalInformation"] : null, // TODO: institution specific keys like: GUTSCHRIFT, ABSCHLUSS, MONATSABSCHLUSS etc 'category_type' => array_key_exists('additionalInformation', $transaction) ? $transaction["additionalInformation"] : '',
'date' => $transaction["bookingDate"], 'date' => $transaction["bookingDate"],
'description' => $description, 'description' => $description,
'participant' => $participant, 'participant' => $participant,

View File

@ -31,8 +31,11 @@ class NordigenController extends BaseController
public function connect(ConnectNordigenBankIntegrationRequest $request) public function connect(ConnectNordigenBankIntegrationRequest $request)
{ {
$data = $request->all(); $data = $request->all();
/** @var array $context */
$context = $request->getTokenContent(); $context = $request->getTokenContent();
$lang = $data['lang'] ?? 'en'; $company = $request->getCompany();
$lang = $company->locale();
$context["lang"] = $lang; $context["lang"] = $lang;
if (!$context) if (!$context)
@ -62,7 +65,7 @@ class NordigenController extends BaseController
"redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid", "redirectUrl" => $context["redirect"] . "?action=nordigen_connect&status=failed&reason=account-config-invalid",
]); ]);
if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) if (!(Ninja::isSelfHost() || (Ninja::isHosted() && $account->isEnterprisePaidClient())))
return view('bank.nordigen.handler', [ return view('bank.nordigen.handler', [
'lang' => $lang, 'lang' => $lang,
'company' => $company, 'company' => $company,
@ -85,7 +88,7 @@ class NordigenController extends BaseController
// redirect to requisition flow // redirect to requisition flow
try { try {
$requisition = $nordigen->createRequisition(config('ninja.app_url') . '/nordigen/confirm', $data['institution_id'], $request->token); $requisition = $nordigen->createRequisition(config('ninja.app_url') . '/nordigen/confirm', $data['institution_id'], $request->token, $lang);
} catch (NordigenException $e) { // TODO: property_exists returns null in these cases... => why => therefore we just get unknown error everytime $responseBody is typeof GuzzleHttp\Psr7\Stream } catch (NordigenException $e) { // TODO: property_exists returns null in these cases... => why => therefore we just get unknown error everytime $responseBody is typeof GuzzleHttp\Psr7\Stream
$responseBody = (string) $e->getResponse()->getBody(); $responseBody = (string) $e->getResponse()->getBody();
@ -128,15 +131,19 @@ class NordigenController extends BaseController
/** /**
* VIEW: Confirm Nordigen Bank Integration (redirect after nordigen flow) * VIEW: Confirm Nordigen Bank Integration (redirect after nordigen flow)
* @param ConnectNordigenBankIntegrationRequest $request * @param ConfirmNordigenBankIntegrationRequest $request
*/ */
public function confirm(ConfirmNordigenBankIntegrationRequest $request) public function confirm(ConfirmNordigenBankIntegrationRequest $request)
{ {
$data = $request->all(); $data = $request->all();
$company = $request->getCompany();
$account = $company->account;
$lang = $company->locale();
/** @var array $context */
$context = $request->getTokenContent(); $context = $request->getTokenContent();
if (!array_key_exists('lang', $data) && $context['lang'] != 'en') if (!array_key_exists('lang', $data) && $context['lang'] != 'en')
return redirect()->route('nordigen.confirm', array_merge(["lang" => $context['lang']], $request->query())); // redirect is required in order for the bank-ui to display everything properly return redirect()->route('nordigen.confirm', array_merge(["lang" => $context['lang']], $request->query()));
$lang = $data['lang'] ?? 'en';
if (!$context || $context["context"] != "nordigen" || !array_key_exists("requisitionId", $context)) if (!$context || $context["context"] != "nordigen" || !array_key_exists("requisitionId", $context))
return view('bank.nordigen.handler', [ return view('bank.nordigen.handler', [
@ -145,9 +152,6 @@ class NordigenController extends BaseController
"redirectUrl" => ($context && array_key_exists("redirect", $context) ? $context["redirect"] : config('ninja.app_url')) . "?action=nordigen_connect&status=failed&reason=ref-invalid", "redirectUrl" => ($context && array_key_exists("redirect", $context) ? $context["redirect"] : config('ninja.app_url')) . "?action=nordigen_connect&status=failed&reason=ref-invalid",
]); ]);
$company = $request->getCompany();
$account = $company->account;
if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key'))) if (!(config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key')))
return view('bank.nordigen.handler', [ return view('bank.nordigen.handler', [
'lang' => $lang, 'lang' => $lang,

View File

@ -212,7 +212,7 @@ class BankIntegrationController extends BaseController
ProcessBankTransactionsYodlee::dispatch($user_account->id, $bank_integration); ProcessBankTransactionsYodlee::dispatch($user_account->id, $bank_integration);
}); });
if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isPaid() && $user_account->plan == 'enterprise'))) if (config('ninja.nordigen.secret_id') && config('ninja.nordigen.secret_key') && (Ninja::isSelfHost() || (Ninja::isHosted() && $user_account->isEnterprisePaidClient())))
$user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) { $user_account->bank_integrations->where("integration_type", BankIntegration::INTEGRATION_TYPE_NORDIGEN)->each(function ($bank_integration) {
ProcessBankTransactionsNordigen::dispatch($bank_integration); ProcessBankTransactionsNordigen::dispatch($bank_integration);
}); });
@ -298,11 +298,14 @@ class BankIntegrationController extends BaseController
$account = $user->account; $account = $user->account;
$bank_integration = BankIntegration::withTrashed()->where('bank_account_id', $acc_id)->orWhere('nordigen_account_id', $acc_id)->company()->firstOrFail(); // @turbo124 please check $bank_integration = BankIntegration::withTrashed()
->where('bank_account_id', $acc_id)
->orWhere('nordigen_account_id', $acc_id)
->company()
->firstOrFail();
if ($bank_integration->integration_type == BankIntegration::INTEGRATION_TYPE_YODLEE) if ($bank_integration->integration_type == BankIntegration::INTEGRATION_TYPE_YODLEE)
$this->removeAccountYodlee($account, $bank_integration); $this->removeAccountYodlee($account, $bank_integration);
// we dont remove Accounts from nordigen, because they could be used within other companies
$this->bank_integration_repo->delete($bank_integration); $this->bank_integration_repo->delete($bank_integration);

View File

@ -36,24 +36,19 @@ class ConnectNordigenBankIntegrationRequest extends Request
public function rules() public function rules()
{ {
return [ return [
'lang' => 'string',
'institution_id' => 'string',
'redirect' => 'string',
]; ];
} }
// @turbo124 @todo please check for validity, when request from frontend
public function prepareForValidation() public function prepareForValidation()
{ {
$input = $this->all(); $input = $this->all();
if (!array_key_exists('redirect', $input)) { $context = $this->getTokenContent();
$context = $this->getTokenContent();
$input["redirect"] = isset($context["is_react"]) && $context['is_react'] ? config('ninja.react_url') . "/#/settings/bank_accounts" : config('ninja.app_url'); $input["redirect"] = isset($context["is_react"]) && $context['is_react'] ? config('ninja.react_url') . "/#/settings/bank_accounts" : config('ninja.app_url');
$this->replace($input); $this->replace($input);
}
} }
public function getTokenContent() public function getTokenContent()
{ {

View File

@ -11,14 +11,19 @@
namespace App\Http\ValidationRules\Account; namespace App\Http\ValidationRules\Account;
use Illuminate\Contracts\Validation\Rule; use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/** /**
* Class BlackListRule. * Class BlackListRule.
*/ */
class BlackListRule implements Rule class BlackListRule implements ValidationRule
{ {
/** Bad domains +/- dispoable email domains */
private array $blacklist = [ private array $blacklist = [
'secure-coinspot.com',
'casasotombo.com',
'otpku.com',
'ckptr.com', 'ckptr.com',
'pretreer.com', 'pretreer.com',
'candassociates.com', 'candassociates.com',
@ -57,6 +62,8 @@ class BlackListRule implements Rule
'10dk.email', '10dk.email',
'10mail.com', '10mail.com',
'10mail.org', '10mail.org',
'10mail.tk',
'10minmail.de',
'10minut.com.pl', '10minut.com.pl',
'10minut.xyz', '10minut.xyz',
'10minutemail.be', '10minutemail.be',
@ -75,6 +82,7 @@ class BlackListRule implements Rule
'10minutemailbox.com', '10minutemailbox.com',
'10minutemails.in', '10minutemails.in',
'10minutenemail.de', '10minutenemail.de',
'10minutenmail.xyz',
'10minutesmail.com', '10minutesmail.com',
'10minutesmail.fr', '10minutesmail.fr',
'10minutmail.pl', '10minutmail.pl',
@ -268,6 +276,7 @@ class BlackListRule implements Rule
'affinitywe.us', 'affinitywe.us',
'affluentwe.us', 'affluentwe.us',
'affordablewe.us', 'affordablewe.us',
'afia.pro',
'afrobacon.com', 'afrobacon.com',
'afterhourswe.us', 'afterhourswe.us',
'agedmail.com', 'agedmail.com',
@ -287,6 +296,8 @@ class BlackListRule implements Rule
'akapost.com', 'akapost.com',
'akerd.com', 'akerd.com',
'akgq701.com', 'akgq701.com',
'akmail.in',
'akugu.com',
'al-qaeda.us', 'al-qaeda.us',
'albionwe.us', 'albionwe.us',
'alchemywe.us', 'alchemywe.us',
@ -294,6 +305,7 @@ class BlackListRule implements Rule
'aliaswe.us', 'aliaswe.us',
'alienware13.com', 'alienware13.com',
'aligamel.com', 'aligamel.com',
'alina-schiesser.ch',
'alisongamel.com', 'alisongamel.com',
'alivance.com', 'alivance.com',
'alivewe.us', 'alivewe.us',
@ -376,6 +388,7 @@ class BlackListRule implements Rule
'antispam.de', 'antispam.de',
'antispam24.de', 'antispam24.de',
'antispammail.de', 'antispammail.de',
'any.pink',
'anyalias.com', 'anyalias.com',
'aoeuhtns.com', 'aoeuhtns.com',
'apfelkorps.de', 'apfelkorps.de',
@ -440,10 +453,12 @@ class BlackListRule implements Rule
'badoop.com', 'badoop.com',
'badpotato.tk', 'badpotato.tk',
'balaket.com', 'balaket.com',
'bangban.uk',
'banit.club', 'banit.club',
'banit.me', 'banit.me',
'bank-opros1.ru', 'bank-opros1.ru',
'bareed.ws', 'bareed.ws',
'barooko.com',
'barryogorman.com', 'barryogorman.com',
'bartdevos.be', 'bartdevos.be',
'basscode.org', 'basscode.org',
@ -451,11 +466,15 @@ class BlackListRule implements Rule
'bazaaboom.com', 'bazaaboom.com',
'bbbbyyzz.info', 'bbbbyyzz.info',
'bbhost.us', 'bbhost.us',
'bbitf.com',
'bbitj.com',
'bbitq.com',
'bcaoo.com', 'bcaoo.com',
'bcast.ws', 'bcast.ws',
'bcb.ro', 'bcb.ro',
'bccto.me', 'bccto.me',
'bdmuzic.pw', 'bdmuzic.pw',
'beaconmessenger.com',
'bearsarefuzzy.com', 'bearsarefuzzy.com',
'beddly.com', 'beddly.com',
'beefmilk.com', 'beefmilk.com',
@ -477,6 +496,7 @@ class BlackListRule implements Rule
'betr.co', 'betr.co',
'bgtmail.com', 'bgtmail.com',
'bgx.ro', 'bgx.ro',
'bheps.com',
'bidourlnks.com', 'bidourlnks.com',
'big1.us', 'big1.us',
'bigprofessor.so', 'bigprofessor.so',
@ -520,9 +540,11 @@ class BlackListRule implements Rule
'bouncr.com', 'bouncr.com',
'boxformail.in', 'boxformail.in',
'boximail.com', 'boximail.com',
'boxmail.lol',
'boxomail.live', 'boxomail.live',
'boxtemp.com.br', 'boxtemp.com.br',
'bptfp.net', 'bptfp.net',
'brand-app.biz',
'brandallday.net', 'brandallday.net',
'brasx.org', 'brasx.org',
'breakthru.com', 'breakthru.com',
@ -543,8 +565,10 @@ class BlackListRule implements Rule
'budaya-tionghoa.com', 'budaya-tionghoa.com',
'budayationghoa.com', 'budayationghoa.com',
'buffemail.com', 'buffemail.com',
'bugfoo.com',
'bugmenever.com', 'bugmenever.com',
'bugmenot.com', 'bugmenot.com',
'bukhariansiddur.com',
'bulrushpress.com', 'bulrushpress.com',
'bum.net', 'bum.net',
'bumpymail.com', 'bumpymail.com',
@ -582,6 +606,7 @@ class BlackListRule implements Rule
'caseedu.tk', 'caseedu.tk',
'cashflow35.com', 'cashflow35.com',
'casualdx.com', 'casualdx.com',
'catgroup.uk',
'cavi.mx', 'cavi.mx',
'cbair.com', 'cbair.com',
'cbes.net', 'cbes.net',
@ -605,6 +630,7 @@ class BlackListRule implements Rule
'cheaphub.net', 'cheaphub.net',
'cheatmail.de', 'cheatmail.de',
'chenbot.email', 'chenbot.email',
'chewydonut.com',
'chibakenma.ml', 'chibakenma.ml',
'chickenkiller.com', 'chickenkiller.com',
'chielo.com', 'chielo.com',
@ -621,6 +647,7 @@ class BlackListRule implements Rule
'chong-mail.org', 'chong-mail.org',
'chumpstakingdumps.com', 'chumpstakingdumps.com',
'cigar-auctions.com', 'cigar-auctions.com',
'civikli.com',
'civx.org', 'civx.org',
'ckaazaza.tk', 'ckaazaza.tk',
'ckiso.com', 'ckiso.com',
@ -637,6 +664,7 @@ class BlackListRule implements Rule
'clonemoi.tk', 'clonemoi.tk',
'cloud-mail.top', 'cloud-mail.top',
'cloudns.cx', 'cloudns.cx',
'clout.wiki',
'clrmail.com', 'clrmail.com',
'cmail.club', 'cmail.club',
'cmail.com', 'cmail.com',
@ -678,6 +706,7 @@ class BlackListRule implements Rule
'crazymailing.com', 'crazymailing.com',
'cream.pink', 'cream.pink',
'crepeau12.com', 'crepeau12.com',
'cringemonster.com',
'cross-law.ga', 'cross-law.ga',
'cross-law.gq', 'cross-law.gq',
'crossmailjet.com', 'crossmailjet.com',
@ -733,6 +762,7 @@ class BlackListRule implements Rule
'daymailonline.com', 'daymailonline.com',
'dayrep.com', 'dayrep.com',
'dbunker.com', 'dbunker.com',
'dcctb.com',
'dcemail.com', 'dcemail.com',
'ddcrew.com', 'ddcrew.com',
'de-a.org', 'de-a.org',
@ -769,6 +799,7 @@ class BlackListRule implements Rule
'dev-null.ga', 'dev-null.ga',
'dev-null.gq', 'dev-null.gq',
'dev-null.ml', 'dev-null.ml',
'developermail.com',
'devnullmail.com', 'devnullmail.com',
'deyom.com', 'deyom.com',
'dharmatel.net', 'dharmatel.net',
@ -800,6 +831,7 @@ class BlackListRule implements Rule
'discardmail.com', 'discardmail.com',
'discardmail.de', 'discardmail.de',
'discos4.com', 'discos4.com',
'dishcatfish.com',
'disign-concept.eu', 'disign-concept.eu',
'disign-revelation.com', 'disign-revelation.com',
'dispo.in', 'dispo.in',
@ -851,10 +883,12 @@ class BlackListRule implements Rule
'domforfb8.tk', 'domforfb8.tk',
'domforfb9.tk', 'domforfb9.tk',
'domozmail.com', 'domozmail.com',
'donebyngle.com',
'donemail.ru', 'donemail.ru',
'dongqing365.com', 'dongqing365.com',
'dontreg.com', 'dontreg.com',
'dontsendmespam.de', 'dontsendmespam.de',
'doojazz.com',
'doquier.tk', 'doquier.tk',
'dotman.de', 'dotman.de',
'dotmsg.com', 'dotmsg.com',
@ -869,13 +903,17 @@ class BlackListRule implements Rule
'dred.ru', 'dred.ru',
'drevo.si', 'drevo.si',
'drivetagdev.com', 'drivetagdev.com',
'drmail.in',
'droolingfanboy.de', 'droolingfanboy.de',
'dropcake.de', 'dropcake.de',
'dropjar.com', 'dropjar.com',
'droplar.com', 'droplar.com',
'dropmail.me', 'dropmail.me',
'dropsin.net', 'dropsin.net',
'drowblock.com',
'dsgvo.party',
'dsgvo.ru', 'dsgvo.ru',
'dshfjdafd.cloud',
'dsiay.com', 'dsiay.com',
'dspwebservices.com', 'dspwebservices.com',
'duam.net', 'duam.net',
@ -944,6 +982,7 @@ class BlackListRule implements Rule
'emailage.ml', 'emailage.ml',
'emailage.tk', 'emailage.tk',
'emailate.com', 'emailate.com',
'emailbin.net',
'emailcu.icu', 'emailcu.icu',
'emaildienst.de', 'emaildienst.de',
'emaildrop.io', 'emaildrop.io',
@ -1017,8 +1056,11 @@ class BlackListRule implements Rule
'eposta.buzz', 'eposta.buzz',
'eposta.work', 'eposta.work',
'eqiluxspam.ga', 'eqiluxspam.ga',
'ereplyzy.com',
'ericjohnson.ml', 'ericjohnson.ml',
'eripo.net',
'ero-tube.org', 'ero-tube.org',
'esadverse.com',
'esbano-ru.ru', 'esbano-ru.ru',
'esc.la', 'esc.la',
'escapehatchapp.com', 'escapehatchapp.com',
@ -1043,16 +1085,19 @@ class BlackListRule implements Rule
'evopo.com', 'evopo.com',
'evyush.com', 'evyush.com',
'exdonuts.com', 'exdonuts.com',
'exelica.com',
'existiert.net', 'existiert.net',
'exitstageleft.net', 'exitstageleft.net',
'explodemail.com', 'explodemail.com',
'express.net.ua', 'express.net.ua',
'extracurricularsociety.com',
'extremail.ru', 'extremail.ru',
'eyepaste.com', 'eyepaste.com',
'ez.lv', 'ez.lv',
'ezehe.com', 'ezehe.com',
'ezfill.com', 'ezfill.com',
'ezstest.com', 'ezstest.com',
'ezztt.com',
'f4k.es', 'f4k.es',
'f5.si', 'f5.si',
'facebook-email.cf', 'facebook-email.cf',
@ -1108,12 +1153,14 @@ class BlackListRule implements Rule
'fbma.tk', 'fbma.tk',
'fddns.ml', 'fddns.ml',
'fdfdsfds.com', 'fdfdsfds.com',
'femailtor.com',
'fer-gabon.org', 'fer-gabon.org',
'fermaxxi.ru', 'fermaxxi.ru',
'fettometern.com', 'fettometern.com',
'fexbox.org', 'fexbox.org',
'fexbox.ru', 'fexbox.ru',
'fexpost.com', 'fexpost.com',
'fextemp.com',
'ficken.de', 'ficken.de',
'fictionsite.com', 'fictionsite.com',
'fightallspam.com', 'fightallspam.com',
@ -1127,6 +1174,7 @@ class BlackListRule implements Rule
'filzmail.com', 'filzmail.com',
'findemail.info', 'findemail.info',
'findu.pl', 'findu.pl',
'finews.biz',
'fir.hk', 'fir.hk',
'firemailbox.club', 'firemailbox.club',
'fitnesrezink.ru', 'fitnesrezink.ru',
@ -1135,12 +1183,14 @@ class BlackListRule implements Rule
'fizmail.com', 'fizmail.com',
'fleckens.hu', 'fleckens.hu',
'flemail.ru', 'flemail.ru',
'fliegender.fish',
'flowu.com', 'flowu.com',
'flu.cc', 'flu.cc',
'fluidsoft.us', 'fluidsoft.us',
'flurred.com', 'flurred.com',
'fly-ts.de', 'fly-ts.de',
'flyinggeek.net', 'flyinggeek.net',
'flymail.tk',
'flyspam.com', 'flyspam.com',
'foobarbot.net', 'foobarbot.net',
'footard.com', 'footard.com',
@ -1158,6 +1208,7 @@ class BlackListRule implements Rule
'fosil.pro', 'fosil.pro',
'foxja.com', 'foxja.com',
'foxtrotter.info', 'foxtrotter.info',
'fr.cr',
'fr.nf', 'fr.nf',
'fr33mail.info', 'fr33mail.info',
'fragolina2.tk', 'fragolina2.tk',
@ -1204,11 +1255,15 @@ class BlackListRule implements Rule
'fuirio.com', 'fuirio.com',
'fukaru.com', 'fukaru.com',
'fukurou.ch', 'fukurou.ch',
'fullangle.org',
'fulvie.com', 'fulvie.com',
'fun64.com', 'fun64.com',
'funnycodesnippets.com', 'funnycodesnippets.com',
'funnymail.de', 'funnymail.de',
'furzauflunge.de', 'furzauflunge.de',
'futuramind.com',
'fuwa.be',
'fuwa.li',
'fuwamofu.com', 'fuwamofu.com',
'fuwari.be', 'fuwari.be',
'fux0ringduh.com', 'fux0ringduh.com',
@ -1291,6 +1346,7 @@ class BlackListRule implements Rule
'giveh2o.info', 'giveh2o.info',
'givememail.club', 'givememail.club',
'givmail.com', 'givmail.com',
'gixenmixen.com',
'glitch.sx', 'glitch.sx',
'globaltouron.com', 'globaltouron.com',
'glubex.com', 'glubex.com',
@ -1304,6 +1360,7 @@ class BlackListRule implements Rule
'gnctr-calgary.com', 'gnctr-calgary.com',
'go2usa.info', 'go2usa.info',
'go2vpn.net', 'go2vpn.net',
'goatmail.uk',
'goemailgo.com', 'goemailgo.com',
'golemico.com', 'golemico.com',
'gomail.in', 'gomail.in',
@ -1363,6 +1420,7 @@ class BlackListRule implements Rule
'guerrillamail.net', 'guerrillamail.net',
'guerrillamail.org', 'guerrillamail.org',
'guerrillamailblock.com', 'guerrillamailblock.com',
'gufum.com',
'gustr.com', 'gustr.com',
'gxemail.men', 'gxemail.men',
'gynzi.co.uk', 'gynzi.co.uk',
@ -1389,6 +1447,7 @@ class BlackListRule implements Rule
'haltospam.com', 'haltospam.com',
'hamham.uk', 'hamham.uk',
'hangxomcuatoilatotoro.ml', 'hangxomcuatoilatotoro.ml',
'happy2023year.com',
'happydomik.ru', 'happydomik.ru',
'harakirimail.com', 'harakirimail.com',
'haribu.com', 'haribu.com',
@ -1467,6 +1526,7 @@ class BlackListRule implements Rule
'huskion.net', 'huskion.net',
'hvastudiesucces.nl', 'hvastudiesucces.nl',
'hwsye.net', 'hwsye.net',
'hypenated-domain.com',
'i2pmail.org', 'i2pmail.org',
'i6.cloudns.cc', 'i6.cloudns.cc',
'iaoss.com', 'iaoss.com',
@ -1476,6 +1536,7 @@ class BlackListRule implements Rule
'ichigo.me', 'ichigo.me',
'icx.in', 'icx.in',
'icx.ro', 'icx.ro',
'icznn.com',
'idx4.com', 'idx4.com',
'idxue.com', 'idxue.com',
'ieatspam.eu', 'ieatspam.eu',
@ -1498,9 +1559,12 @@ class BlackListRule implements Rule
'imgof.com', 'imgof.com',
'imgv.de', 'imgv.de',
'immo-gerance.info', 'immo-gerance.info',
'imperialcnk.com',
'imstations.com', 'imstations.com',
'imul.info', 'imul.info',
'in-ulm.de', 'in-ulm.de',
'in2reach.com',
'inactivemachine.com',
'inbax.tk', 'inbax.tk',
'inbound.plus', 'inbound.plus',
'inbox.si', 'inbox.si',
@ -1530,6 +1594,7 @@ class BlackListRule implements Rule
'ineec.net', 'ineec.net',
'infocom.zp.ua', 'infocom.zp.ua',
'inggo.org', 'inggo.org',
'inkiny.com',
'inkomail.com', 'inkomail.com',
'inmynetwork.tk', 'inmynetwork.tk',
'inoutmail.de', 'inoutmail.de',
@ -1540,12 +1605,16 @@ class BlackListRule implements Rule
'insanumingeniumhomebrew.com', 'insanumingeniumhomebrew.com',
'insorg-mail.info', 'insorg-mail.info',
'instaddr.ch', 'instaddr.ch',
'instaddr.uk',
'instaddr.win',
'instance-email.com', 'instance-email.com',
'instant-mail.de', 'instant-mail.de',
'instantblingmail.info', 'instantblingmail.info',
'instantemailaddress.com', 'instantemailaddress.com',
'instantmail.fr', 'instantmail.fr',
'instmail.uk',
'internet-v-stavropole.ru', 'internet-v-stavropole.ru',
'internetkeno.com',
'internetoftags.com', 'internetoftags.com',
'interstats.org', 'interstats.org',
'intersteller.com', 'intersteller.com',
@ -1577,6 +1646,7 @@ class BlackListRule implements Rule
'italy-mail.com', 'italy-mail.com',
'itcompu.com', 'itcompu.com',
'itfast.net', 'itfast.net',
'itsjiff.com',
'itunesgiftcodegenerator.com', 'itunesgiftcodegenerator.com',
'iubridge.com', 'iubridge.com',
'iuemail.men', 'iuemail.men',
@ -1585,6 +1655,7 @@ class BlackListRule implements Rule
'ixx.io', 'ixx.io',
'j-p.us', 'j-p.us',
'jafps.com', 'jafps.com',
'jaga.email',
'jajxz.com', 'jajxz.com',
'janproz.com', 'janproz.com',
'jaqis.com', 'jaqis.com',
@ -1599,11 +1670,15 @@ class BlackListRule implements Rule
'jetable.net', 'jetable.net',
'jetable.org', 'jetable.org',
'jetable.pp.ua', 'jetable.pp.ua',
'ji5.de',
'ji6.de',
'ji7.de',
'jiooq.com', 'jiooq.com',
'jmail.ovh', 'jmail.ovh',
'jmail.ro', 'jmail.ro',
'jnxjn.com', 'jnxjn.com',
'jobbikszimpatizans.hu', 'jobbikszimpatizans.hu',
'jobbrett.com',
'jobposts.net', 'jobposts.net',
'jobs-to-be-done.net', 'jobs-to-be-done.net',
'joelpet.com', 'joelpet.com',
@ -1660,6 +1735,8 @@ class BlackListRule implements Rule
'killmail.com', 'killmail.com',
'killmail.net', 'killmail.net',
'kimsdisk.com', 'kimsdisk.com',
'kinda.email',
'kindamail.com',
'kingsq.ga', 'kingsq.ga',
'kino-100.ru', 'kino-100.ru',
'kiois.com', 'kiois.com',
@ -1668,16 +1745,20 @@ class BlackListRule implements Rule
'kitnastar.com', 'kitnastar.com',
'kjkszpjcompany.com', 'kjkszpjcompany.com',
'kkmail.be', 'kkmail.be',
'kkoup.com',
'kksm.be', 'kksm.be',
'klassmaster.com', 'klassmaster.com',
'klassmaster.net', 'klassmaster.net',
'klick-tipp.us', 'klick-tipp.us',
'klipschx12.com', 'klipschx12.com',
'kloap.com', 'kloap.com',
'klovenode.com',
'kludgemush.com', 'kludgemush.com',
'klzlk.com', 'klzlk.com',
'kmail.li', 'kmail.li',
'kmail.live',
'kmhow.com', 'kmhow.com',
'knickerbockerban.de',
'knol-power.nl', 'knol-power.nl',
'kobrandly.com', 'kobrandly.com',
'kommunity.biz', 'kommunity.biz',
@ -1711,6 +1792,7 @@ class BlackListRule implements Rule
'kwilco.net', 'kwilco.net',
'kyal.pl', 'kyal.pl',
'kyois.com', 'kyois.com',
'kzccv.com',
'l-c-a.us', 'l-c-a.us',
'l33r.eu', 'l33r.eu',
'l6factors.com', 'l6factors.com',
@ -1725,9 +1807,12 @@ class BlackListRule implements Rule
'lak.pp.ua', 'lak.pp.ua',
'lakelivingstonrealestate.com', 'lakelivingstonrealestate.com',
'lakqs.com', 'lakqs.com',
'lamasticots.com',
'lambsauce.de',
'landmail.co', 'landmail.co',
'laoeq.com', 'laoeq.com',
'larisia.com', 'larisia.com',
'larland.com',
'last-chance.pro', 'last-chance.pro',
'lastmail.co', 'lastmail.co',
'lastmail.com', 'lastmail.com',
@ -1757,6 +1842,7 @@ class BlackListRule implements Rule
'ligsb.com', 'ligsb.com',
'lillemap.net', 'lillemap.net',
'lilo.me', 'lilo.me',
'lilspam.com',
'lindenbaumjapan.com', 'lindenbaumjapan.com',
'link2mail.net', 'link2mail.net',
'linkedintuts2016.pw', 'linkedintuts2016.pw',
@ -1802,6 +1888,8 @@ class BlackListRule implements Rule
'lukop.dk', 'lukop.dk',
'luv2.us', 'luv2.us',
'lyfestylecreditsolutions.com', 'lyfestylecreditsolutions.com',
'lyft.live',
'lyricspad.net',
'lzoaq.com', 'lzoaq.com',
'm21.cc', 'm21.cc',
'm4ilweb.info', 'm4ilweb.info',
@ -1847,6 +1935,7 @@ class BlackListRule implements Rule
'mailapp.top', 'mailapp.top',
'mailback.com', 'mailback.com',
'mailbidon.com', 'mailbidon.com',
'mailbiscuit.com',
'mailbiz.biz', 'mailbiz.biz',
'mailblocks.com', 'mailblocks.com',
'mailbox.in.ua', 'mailbox.in.ua',
@ -1876,6 +1965,7 @@ class BlackListRule implements Rule
'mailed.ro', 'mailed.ro',
'maileimer.de', 'maileimer.de',
'maileme101.com', 'maileme101.com',
'mailers.edu.pl',
'mailexpire.com', 'mailexpire.com',
'mailf5.com', 'mailf5.com',
'mailfa.tk', 'mailfa.tk',
@ -1943,6 +2033,7 @@ class BlackListRule implements Rule
'mailonaut.com', 'mailonaut.com',
'mailorc.com', 'mailorc.com',
'mailorg.org', 'mailorg.org',
'mailosaur.net',
'mailox.fun', 'mailox.fun',
'mailpick.biz', 'mailpick.biz',
'mailpluss.com', 'mailpluss.com',
@ -2006,18 +2097,22 @@ class BlackListRule implements Rule
'mcache.net', 'mcache.net',
'mciek.com', 'mciek.com',
'mdhc.tk', 'mdhc.tk',
'mdz.email',
'meantinc.com', 'meantinc.com',
'mebelnu.info', 'mebelnu.info',
'mechanicalresumes.com', 'mechanicalresumes.com',
'medkabinet-uzi.ru', 'medkabinet-uzi.ru',
'meepsheep.eu', 'meepsheep.eu',
'meidecn.com',
'meinspamschutz.de', 'meinspamschutz.de',
'meltedbrownies.com', 'meltedbrownies.com',
'meltmail.com', 'meltmail.com',
'memsg.site', 'memsg.site',
'mentonit.net', 'mentonit.net',
'mepost.pw', 'mepost.pw',
'merepost.com',
'merry.pink', 'merry.pink',
'meruado.uk',
'messagebeamer.de', 'messagebeamer.de',
'messwiththebestdielikethe.rest', 'messwiththebestdielikethe.rest',
'metadownload.org', 'metadownload.org',
@ -2043,6 +2138,7 @@ class BlackListRule implements Rule
'migumail.com', 'migumail.com',
'mihep.com', 'mihep.com',
'mijnhva.nl', 'mijnhva.nl',
'minimail.gq',
'ministry-of-silly-walks.de', 'ministry-of-silly-walks.de',
'minsmail.com', 'minsmail.com',
'mintemail.com', 'mintemail.com',
@ -2054,6 +2150,7 @@ class BlackListRule implements Rule
'mjukglass.nu', 'mjukglass.nu',
'mkpfilm.com', 'mkpfilm.com',
'ml8.ca', 'ml8.ca',
'mliok.com',
'mm.my', 'mm.my',
'mm5.se', 'mm5.se',
'mnode.me', 'mnode.me',
@ -2109,6 +2206,7 @@ class BlackListRule implements Rule
'mucincanon.com', 'mucincanon.com',
'muehlacker.tk', 'muehlacker.tk',
'muell.icu', 'muell.icu',
'muell.io',
'muell.monster', 'muell.monster',
'muell.xyz', 'muell.xyz',
'muellemail.com', 'muellemail.com',
@ -2128,16 +2226,19 @@ class BlackListRule implements Rule
'mycleaninbox.net', 'mycleaninbox.net',
'mycorneroftheinter.net', 'mycorneroftheinter.net',
'myde.ml', 'myde.ml',
'mydefipet.live',
'mydemo.equipment', 'mydemo.equipment',
'myecho.es', 'myecho.es',
'myemailboxy.com', 'myemailboxy.com',
'mygeoweb.info', 'mygeoweb.info',
'myindohome.services', 'myindohome.services',
'myinfoinc.com',
'myinterserver.ml', 'myinterserver.ml',
'mykickassideas.com', 'mykickassideas.com',
'mymail-in.net', 'mymail-in.net',
'mymail90.com', 'mymail90.com',
'mymailoasis.com', 'mymailoasis.com',
'mymaily.lol',
'mynetstore.de', 'mynetstore.de',
'myopang.com', 'myopang.com',
'mypacks.net', 'mypacks.net',
@ -2171,10 +2272,12 @@ class BlackListRule implements Rule
'naslazhdai.ru', 'naslazhdai.ru',
'nationalgardeningclub.com', 'nationalgardeningclub.com',
'nawmin.info', 'nawmin.info',
'naymedia.com',
'nbzmr.com', 'nbzmr.com',
'negated.com', 'negated.com',
'neko2.net', 'neko2.net',
'nekochan.fr', 'nekochan.fr',
'nekosan.uk',
'neomailbox.com', 'neomailbox.com',
'neotlozhniy-zaim.ru', 'neotlozhniy-zaim.ru',
'nepwk.com', 'nepwk.com',
@ -2263,6 +2366,7 @@ class BlackListRule implements Rule
'nwytg.com', 'nwytg.com',
'nwytg.net', 'nwytg.net',
'ny7.me', 'ny7.me',
'nyasan.com',
'nypato.com', 'nypato.com',
'nyrmusic.com', 'nyrmusic.com',
'o2stk.org', 'o2stk.org',
@ -2280,6 +2384,7 @@ class BlackListRule implements Rule
'oepia.com', 'oepia.com',
'oerpub.org', 'oerpub.org',
'offshore-proxies.net', 'offshore-proxies.net',
'ofisher.net',
'ohaaa.de', 'ohaaa.de',
'ohi.tw', 'ohi.tw',
'oida.icu', 'oida.icu',
@ -2305,6 +2410,7 @@ class BlackListRule implements Rule
'onlatedotcom.info', 'onlatedotcom.info',
'online.ms', 'online.ms',
'onlineidea.info', 'onlineidea.info',
'onlyapp.net',
'onqin.com', 'onqin.com',
'ontyne.biz', 'ontyne.biz',
'oohioo.com', 'oohioo.com',
@ -2330,6 +2436,7 @@ class BlackListRule implements Rule
'ourklips.com', 'ourklips.com',
'ourpreviewdomain.com', 'ourpreviewdomain.com',
'outlawspam.com', 'outlawspam.com',
'outlook.edu.pl',
'outmail.win', 'outmail.win',
'ovomail.co', 'ovomail.co',
'ovpn.to', 'ovpn.to',
@ -2337,6 +2444,7 @@ class BlackListRule implements Rule
'owlpic.com', 'owlpic.com',
'ownsyou.de', 'ownsyou.de',
'oxopoha.com', 'oxopoha.com',
'ozatvn.com',
'ozyl.de', 'ozyl.de',
'p-banlis.ru', 'p-banlis.ru',
'p33.org', 'p33.org',
@ -2347,6 +2455,7 @@ class BlackListRule implements Rule
'pagamenti.tk', 'pagamenti.tk',
'paharpurmim.ga', 'paharpurmim.ga',
'pakadebu.ga', 'pakadebu.ga',
'pamaweb.com',
'pancakemail.com', 'pancakemail.com',
'papierkorb.me', 'papierkorb.me',
'paplease.com', 'paplease.com',
@ -2384,6 +2493,8 @@ class BlackListRule implements Rule
'pisls.com', 'pisls.com',
'pitaniezdorovie.ru', 'pitaniezdorovie.ru',
'pivo-bar.ru', 'pivo-bar.ru',
'pixiil.com',
'pizzajunk.com',
'pjjkp.com', 'pjjkp.com',
'placebomail10.com', 'placebomail10.com',
'pleasenoham.org', 'pleasenoham.org',
@ -2435,6 +2546,7 @@ class BlackListRule implements Rule
'prin.be', 'prin.be',
'privacy.net', 'privacy.net',
'privatdemail.net', 'privatdemail.net',
'privmail.edu.pl',
'privy-mail.com', 'privy-mail.com',
'privy-mail.de', 'privy-mail.de',
'privymail.de', 'privymail.de',
@ -2454,6 +2566,7 @@ class BlackListRule implements Rule
'prtz.eu', 'prtz.eu',
'psh.me', 'psh.me',
'psles.com', 'psles.com',
'psnator.com',
'psoxs.com', 'psoxs.com',
'puglieisi.com', 'puglieisi.com',
'puji.pro', 'puji.pro',
@ -2464,11 +2577,13 @@ class BlackListRule implements Rule
'put2.net', 'put2.net',
'puttanamaiala.tk', 'puttanamaiala.tk',
'putthisinyourspamdatabase.com', 'putthisinyourspamdatabase.com',
'pwpwa.com',
'pwrby.com', 'pwrby.com',
'qasti.com', 'qasti.com',
'qbfree.us', 'qbfree.us',
'qc.to', 'qc.to',
'qibl.at', 'qibl.at',
'qiott.com',
'qipmail.net', 'qipmail.net',
'qiq.us', 'qiq.us',
'qisdo.com', 'qisdo.com',
@ -2485,6 +2600,7 @@ class BlackListRule implements Rule
'quickinbox.com', 'quickinbox.com',
'quickmail.nl', 'quickmail.nl',
'quicksend.ch', 'quicksend.ch',
'quipas.com',
'ququb.com', 'ququb.com',
'qvy.me', 'qvy.me',
'qwickmail.com', 'qwickmail.com',
@ -2496,6 +2612,7 @@ class BlackListRule implements Rule
'raetp9.com', 'raetp9.com',
'rainbowly.ml', 'rainbowly.ml',
'raketenmann.de', 'raketenmann.de',
'ramenmail.de',
'rancidhome.net', 'rancidhome.net',
'randomail.io', 'randomail.io',
'randomail.net', 'randomail.net',
@ -2512,6 +2629,7 @@ class BlackListRule implements Rule
're-gister.com', 're-gister.com',
'reality-concept.club', 'reality-concept.club',
'reallymymail.com', 'reallymymail.com',
'realquickemail.com',
'realtyalerts.ca', 'realtyalerts.ca',
'rebates.stream', 'rebates.stream',
'receiveee.com', 'receiveee.com',
@ -2542,6 +2660,7 @@ class BlackListRule implements Rule
'rippb.com', 'rippb.com',
'risingsuntouch.com', 'risingsuntouch.com',
'riski.cf', 'riski.cf',
'risu.be',
'rklips.com', 'rklips.com',
'rkomo.com', 'rkomo.com',
'rm2rf.com', 'rm2rf.com',
@ -2578,6 +2697,7 @@ class BlackListRule implements Rule
's33db0x.com', 's33db0x.com',
'sabrestlouis.com', 'sabrestlouis.com',
'sackboii.com', 'sackboii.com',
'saeoil.com',
'safaat.cf', 'safaat.cf',
'safermail.info', 'safermail.info',
'safersignup.de', 'safersignup.de',
@ -2630,10 +2750,13 @@ class BlackListRule implements Rule
'sexforswingers.com', 'sexforswingers.com',
'sexical.com', 'sexical.com',
'sexyalwasmi.top', 'sexyalwasmi.top',
'sfolkar.com',
'shadap.org', 'shadap.org',
'shalar.net', 'shalar.net',
'sharedmailbox.org', 'sharedmailbox.org',
'sharkfaces.com',
'sharklasers.com', 'sharklasers.com',
'shchiba.uk',
'sheryli.com', 'sheryli.com',
'shhmail.com', 'shhmail.com',
'shhuut.org', 'shhuut.org',
@ -2662,6 +2785,7 @@ class BlackListRule implements Rule
'sify.com', 'sify.com',
'sika3.com', 'sika3.com',
'sikux.com', 'sikux.com',
'silenceofthespam.com',
'siliwangi.ga', 'siliwangi.ga',
'silvercoin.life', 'silvercoin.life',
'sim-simka.ru', 'sim-simka.ru',
@ -2681,6 +2805,7 @@ class BlackListRule implements Rule
'skrx.tk', 'skrx.tk',
'sky-inbox.com', 'sky-inbox.com',
'sky-ts.de', 'sky-ts.de',
'skygazerhub.com',
'skyrt.de', 'skyrt.de',
'slapsfromlastnight.com', 'slapsfromlastnight.com',
'slaskpost.se', 'slaskpost.se',
@ -2698,6 +2823,7 @@ class BlackListRule implements Rule
'smapfree24.eu', 'smapfree24.eu',
'smapfree24.info', 'smapfree24.info',
'smapfree24.org', 'smapfree24.org',
'smartnator.com',
'smarttalent.pw', 'smarttalent.pw',
'smashmail.de', 'smashmail.de',
'smellfear.com', 'smellfear.com',
@ -2705,12 +2831,14 @@ class BlackListRule implements Rule
'smellypotato.tk', 'smellypotato.tk',
'smtp99.com', 'smtp99.com',
'smwg.info', 'smwg.info',
'snakebutt.com',
'snakemail.com', 'snakemail.com',
'snapwet.com', 'snapwet.com',
'sneakmail.de', 'sneakmail.de',
'snece.com', 'snece.com',
'social-mailer.tk', 'social-mailer.tk',
'socialfurry.org', 'socialfurry.org',
'sociallymediocre.com',
'sofia.re', 'sofia.re',
'sofimail.com', 'sofimail.com',
'sofort-mail.de', 'sofort-mail.de',
@ -2731,6 +2859,7 @@ class BlackListRule implements Rule
'soodmail.com', 'soodmail.com',
'soodomail.com', 'soodomail.com',
'soodonims.com', 'soodonims.com',
'soombo.com',
'soon.it', 'soon.it',
'spacebazzar.ru', 'spacebazzar.ru',
'spam-be-gone.com', 'spam-be-gone.com',
@ -2763,6 +2892,7 @@ class BlackListRule implements Rule
'spamday.com', 'spamday.com',
'spamdecoy.net', 'spamdecoy.net',
'spamex.com', 'spamex.com',
'spamfellas.com',
'spamfighter.cf', 'spamfighter.cf',
'spamfighter.ga', 'spamfighter.ga',
'spamfighter.gq', 'spamfighter.gq',
@ -2791,6 +2921,7 @@ class BlackListRule implements Rule
'spamobox.com', 'spamobox.com',
'spamoff.de', 'spamoff.de',
'spamsalad.in', 'spamsalad.in',
'spamsandwich.com',
'spamslicer.com', 'spamslicer.com',
'spamsphere.com', 'spamsphere.com',
'spamspot.com', 'spamspot.com',
@ -2810,11 +2941,13 @@ class BlackListRule implements Rule
'spikio.com', 'spikio.com',
'spindl-e.com', 'spindl-e.com',
'spoofmail.de', 'spoofmail.de',
'sportrid.com',
'spr.io', 'spr.io',
'spritzzone.de', 'spritzzone.de',
'spruzme.com', 'spruzme.com',
'spybox.de', 'spybox.de',
'spymail.com', 'spymail.com',
'spymail.one',
'squizzy.de', 'squizzy.de',
'squizzy.net', 'squizzy.net',
'sroff.com', 'sroff.com',
@ -2852,10 +2985,12 @@ class BlackListRule implements Rule
'submic.com', 'submic.com',
'suburbanthug.com', 'suburbanthug.com',
'suckmyd.com', 'suckmyd.com',
'sudern.de',
'sueshaw.com', 'sueshaw.com',
'suexamplesb.com', 'suexamplesb.com',
'suioe.com', 'suioe.com',
'super-auswahl.de', 'super-auswahl.de',
'superblohey.com',
'supergreatmail.com', 'supergreatmail.com',
'supermailer.jp', 'supermailer.jp',
'superplatyna.com', 'superplatyna.com',
@ -2872,6 +3007,7 @@ class BlackListRule implements Rule
'sweetxxx.de', 'sweetxxx.de',
'swift-mail.net', 'swift-mail.net',
'swift10minutemail.com', 'swift10minutemail.com',
'syinxun.com',
'sylvannet.com', 'sylvannet.com',
'symphonyresume.com', 'symphonyresume.com',
'syosetu.gq', 'syosetu.gq',
@ -2891,6 +3027,8 @@ class BlackListRule implements Rule
'tastrg.com', 'tastrg.com',
'taukah.com', 'taukah.com',
'tb-on-line.net', 'tb-on-line.net',
'tcwlm.com',
'tcwlx.com',
'tdtda.com', 'tdtda.com',
'tech69.com', 'tech69.com',
'techblast.ch', 'techblast.ch',
@ -2901,6 +3039,7 @@ class BlackListRule implements Rule
'teewars.org', 'teewars.org',
'tefl.ro', 'tefl.ro',
'telecomix.pl', 'telecomix.pl',
'teleg.eu',
'teleworm.com', 'teleworm.com',
'teleworm.us', 'teleworm.us',
'tellos.xyz', 'tellos.xyz',
@ -2965,6 +3104,7 @@ class BlackListRule implements Rule
'thecloudindex.com', 'thecloudindex.com',
'thediamants.org', 'thediamants.org',
'thedirhq.info', 'thedirhq.info',
'theeyeoftruth.com',
'thejoker5.com', 'thejoker5.com',
'thelightningmail.net', 'thelightningmail.net',
'thelimestones.com', 'thelimestones.com',
@ -2974,6 +3114,7 @@ class BlackListRule implements Rule
'thereddoors.online', 'thereddoors.online',
'theroyalweb.club', 'theroyalweb.club',
'thescrappermovie.com', 'thescrappermovie.com',
'thespamfather.com',
'theteastory.info', 'theteastory.info',
'thex.ro', 'thex.ro',
'thichanthit.com', 'thichanthit.com',
@ -3010,9 +3151,13 @@ class BlackListRule implements Rule
'tkitc.de', 'tkitc.de',
'tlpn.org', 'tlpn.org',
'tmail.com', 'tmail.com',
'tmail.io',
'tmail.ws', 'tmail.ws',
'tmail3.com',
'tmail9.com',
'tmailinator.com', 'tmailinator.com',
'tmails.net', 'tmails.net',
'tmmbt.net',
'tmpbox.net', 'tmpbox.net',
'tmpemails.com', 'tmpemails.com',
'tmpeml.com', 'tmpeml.com',
@ -3020,6 +3165,7 @@ class BlackListRule implements Rule
'tmpjr.me', 'tmpjr.me',
'tmpmail.net', 'tmpmail.net',
'tmpmail.org', 'tmpmail.org',
'tmpx.sa.com',
'toddsbighug.com', 'toddsbighug.com',
'tofeat.com', 'tofeat.com',
'toiea.com', 'toiea.com',
@ -3049,6 +3195,7 @@ class BlackListRule implements Rule
'totoan.info', 'totoan.info',
'tourcc.com', 'tourcc.com',
'tp-qa-mail.com', 'tp-qa-mail.com',
'tpwlb.com',
'tqoai.com', 'tqoai.com',
'tqosi.com', 'tqosi.com',
'tradermail.info', 'tradermail.info',
@ -3097,6 +3244,7 @@ class BlackListRule implements Rule
'trialmail.de', 'trialmail.de',
'trickmail.net', 'trickmail.net',
'trillianpro.com', 'trillianpro.com',
'triots.com',
'trixtrux1.ru', 'trixtrux1.ru',
'trollproject.com', 'trollproject.com',
'tropicalbass.info', 'tropicalbass.info',
@ -3112,6 +3260,7 @@ class BlackListRule implements Rule
'turoid.com', 'turoid.com',
'turual.com', 'turual.com',
'turuma.com', 'turuma.com',
'tutuapp.bid',
'tvchd.com', 'tvchd.com',
'tverya.com', 'tverya.com',
'twinmail.de', 'twinmail.de',
@ -3150,6 +3299,7 @@ class BlackListRule implements Rule
'unit7lahaina.com', 'unit7lahaina.com',
'unmail.ru', 'unmail.ru',
'uooos.com', 'uooos.com',
'uorak.com',
'upliftnow.com', 'upliftnow.com',
'uplipht.com', 'uplipht.com',
'uploadnolimit.com', 'uploadnolimit.com',
@ -3268,6 +3418,7 @@ class BlackListRule implements Rule
'watchever.biz', 'watchever.biz',
'watchfull.net', 'watchfull.net',
'watchironman3onlinefreefullmovie.com', 'watchironman3onlinefreefullmovie.com',
'waterisgone.com',
'wazabi.club', 'wazabi.club',
'wbdev.tech', 'wbdev.tech',
'wbml.net', 'wbml.net',
@ -3307,6 +3458,7 @@ class BlackListRule implements Rule
'wegwrfmail.de', 'wegwrfmail.de',
'wegwrfmail.net', 'wegwrfmail.net',
'wegwrfmail.org', 'wegwrfmail.org',
'weizixu.com',
'wekawa.com', 'wekawa.com',
'welikecookies.com', 'welikecookies.com',
'wellsfargocomcardholders.com', 'wellsfargocomcardholders.com',
@ -3316,6 +3468,7 @@ class BlackListRule implements Rule
'wfgdfhj.tk', 'wfgdfhj.tk',
'wg0.com', 'wg0.com',
'wh4f.org', 'wh4f.org',
'whaaaaaaaaaat.com',
'whatiaas.com', 'whatiaas.com',
'whatifanalytics.com', 'whatifanalytics.com',
'whatpaas.com', 'whatpaas.com',
@ -3327,6 +3480,7 @@ class BlackListRule implements Rule
'wickmail.net', 'wickmail.net',
'widaryanto.info', 'widaryanto.info',
'widget.gg', 'widget.gg',
'wiemei.com',
'wierie.tk', 'wierie.tk',
'wifimaple.com', 'wifimaple.com',
'wifioak.com', 'wifioak.com',
@ -3355,6 +3509,7 @@ class BlackListRule implements Rule
'wudet.men', 'wudet.men',
'wuespdj.xyz', 'wuespdj.xyz',
'wupics.com', 'wupics.com',
'wuuvo.com',
'wuzup.net', 'wuzup.net',
'wuzupmail.net', 'wuzupmail.net',
'wwjmp.com', 'wwjmp.com',
@ -3387,6 +3542,9 @@ class BlackListRule implements Rule
'xrap.de', 'xrap.de',
'xrho.com', 'xrho.com',
'xvx.us', 'xvx.us',
'xwaretech.com',
'xwaretech.info',
'xwaretech.net',
'xww.ro', 'xww.ro',
'xxhamsterxx.ga', 'xxhamsterxx.ga',
'xxi2.com', 'xxi2.com',
@ -3463,6 +3621,7 @@ class BlackListRule implements Rule
'zebins.eu', 'zebins.eu',
'zehnminuten.de', 'zehnminuten.de',
'zehnminutenmail.de', 'zehnminutenmail.de',
'zemzar.net',
'zepp.dk', 'zepp.dk',
'zetmail.com', 'zetmail.com',
'zfymail.com', 'zfymail.com',
@ -3473,6 +3632,7 @@ class BlackListRule implements Rule
'zhorachu.com', 'zhorachu.com',
'zik.dj', 'zik.dj',
'zipcad.com', 'zipcad.com',
'zipcatfish.com',
'zipo1.gq', 'zipo1.gq',
'zippymail.info', 'zippymail.info',
'zipsendtest.com', 'zipsendtest.com',
@ -3494,27 +3654,13 @@ class BlackListRule implements Rule
'zzz.com', 'zzz.com',
]; ];
/** public function validate(string $attribute, mixed $value, Closure $fail): void
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value): bool
{ {
$parts = explode("@", $value); $parts = explode("@", $value);
if (is_array($parts)) { if (is_array($parts) && in_array($parts[1], $this->blacklist)) {
return ! in_array($parts[1], $this->blacklist); $fail('This domain is blacklisted, if you think this is in error, please email contact@invoiceninja.com');
} else {
return true;
} }
} }
/**
* @return string
*/
public function message(): string
{
return 'This domain is blacklisted, if you think this is in error, please email contact@invoiceninja.com';
}
} }

View File

@ -11,32 +11,26 @@
namespace App\Http\ValidationRules\Account; namespace App\Http\ValidationRules\Account;
use Illuminate\Contracts\Validation\Rule; use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
/** /**
* Class EmailBlackListRule. * Class EmailBlackListRule.
*/ */
class EmailBlackListRule implements Rule class EmailBlackListRule implements ValidationRule
{ {
public array $blacklist = [ public array $blacklist = [
'noddy@invoiceninja.com',
]; ];
/**
* @param string $attribute public function validate(string $attribute, mixed $value, Closure $fail): void
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{ {
return ! in_array($value, $this->blacklist);
if (in_array($value, $this->blacklist)) {
$fail('This email address is blacklisted, if you think this is in error, please email contact@invoiceninja.com');
}
} }
/**
* @return string
*/
public function message()
{
return 'This email address is blacklisted, if you think this is in error, please email contact@invoiceninja.com';
}
} }

View File

@ -35,7 +35,7 @@ class ProcessBankTransactionsNordigen implements ShouldQueue
public Company $company; public Company $company;
public Nordigen $nordigen; public Nordigen $nordigen;
public $nordigen_account; public $nordigen_account;
private bool $stop_loop = false;
/** /**
* Create a new job instance. * Create a new job instance.
*/ */

View File

@ -162,7 +162,7 @@ class ProcessBankTransactionsYodlee implements ShouldQueue
$now = now(); $now = now();
foreach ($transactions as $transaction) { foreach ($transactions as $transaction) {
if (BankTransaction::query()->where('transaction_id', $transaction['transaction_id'])->where('company_id', $this->company->id)->where('bank_integration_id', $this->bank_integration->id)->withTrashed()->exists()) { // @turbo124 was not scoped to bank_integration_id => from my pov this should be present, because when an account was historized (is_deleted) a transaction can occur multiple (in the archived bank_integration and in the new one if (BankTransaction::query()->where('transaction_id', $transaction['transaction_id'])->where('company_id', $this->company->id)->where('bank_integration_id', $this->bank_integration->id)->withTrashed()->exists()) {
continue; continue;
} }

View File

@ -64,12 +64,12 @@ class BankTransactionSync implements ShouldQueue
private function processYodlee() private function processYodlee()
{ {
if (Ninja::isHosted()) { // @turbo124 @todo I migrated the schedule for the job within the kernel to execute on all platforms and use the same expression here to determine if yodlee can run or not. Please chek/verify if (Ninja::isHosted()) {
nlog("syncing transactions - yodlee"); nlog("syncing transactions - yodlee");
Account::with('bank_integrations')->whereNotNull('bank_integration_account_id')->cursor()->each(function ($account) { Account::with('bank_integrations')->whereNotNull('bank_integration_account_id')->cursor()->each(function ($account) {
if ($account->isPaid() && $account->plan == 'enterprise') { if ($account->isEnterprisePaidClient()) {
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) { $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_YODLEE)->where('auto_sync', true)->cursor()->each(function ($bank_integration) use ($account) {
(new ProcessBankTransactionsYodlee($account->id, $bank_integration))->handle(); (new ProcessBankTransactionsYodlee($account->id, $bank_integration))->handle();
}); });
@ -80,12 +80,12 @@ class BankTransactionSync implements ShouldQueue
} }
private function processNordigen() private function processNordigen()
{ {
if (config("ninja.nordigen.secret_id") && config("ninja.nordigen.secret_key")) { // @turbo124 check condition, when to execute this should be placed here (isSelfHosted || isPro/isEnterprise) if (config("ninja.nordigen.secret_id") && config("ninja.nordigen.secret_key")) {
nlog("syncing transactions - nordigen"); nlog("syncing transactions - nordigen");
Account::with('bank_integrations')->cursor()->each(function ($account) { Account::with('bank_integrations')->cursor()->each(function ($account) {
if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isPaid() && $account->plan == 'enterprise'))) { if ((Ninja::isSelfHost() || (Ninja::isHosted() && $account->isEnterprisePaidClient()))) {
$account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) { $account->bank_integrations()->where('integration_type', BankIntegration::INTEGRATION_TYPE_NORDIGEN)->where('auto_sync', true)->cursor()->each(function ($bank_integration) {
(new ProcessBankTransactionsNordigen($bank_integration))->handle(); (new ProcessBankTransactionsNordigen($bank_integration))->handle();
}); });

View File

@ -30,6 +30,7 @@ use Illuminate\Foundation\Bus\Dispatchable;
use App\DataMapper\Analytics\Mail\EmailSpam; use App\DataMapper\Analytics\Mail\EmailSpam;
use App\DataMapper\Analytics\Mail\EmailBounce; use App\DataMapper\Analytics\Mail\EmailBounce;
use App\Notifications\Ninja\EmailSpamNotification; use App\Notifications\Ninja\EmailSpamNotification;
use App\Notifications\Ninja\EmailBounceNotification;
class ProcessPostmarkWebhook implements ShouldQueue class ProcessPostmarkWebhook implements ShouldQueue
{ {
@ -103,6 +104,11 @@ class ProcessPostmarkWebhook implements ShouldQueue
case 'Delivery': case 'Delivery':
return $this->processDelivery(); return $this->processDelivery();
case 'Bounce': case 'Bounce':
if($this->request['Subject'] == ctrans('texts.confirmation_subject')) {
$company->notification(new EmailBounceNotification($this->request['Email']))->ninja();
}
return $this->processBounce(); return $this->processBounce();
case 'SpamComplaint': case 'SpamComplaint':
return $this->processSpamComplaint(); return $this->processSpamComplaint();
@ -263,8 +269,6 @@ class ProcessPostmarkWebhook implements ShouldQueue
(new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle(); (new SystemLogger($data, SystemLog::CATEGORY_MAIL, SystemLog::EVENT_MAIL_BOUNCED, SystemLog::TYPE_WEBHOOK_RESPONSE, $this->invitation->contact->client, $this->invitation->company))->handle();
// if(config('ninja.notification.slack'))
// $this->invitation->company->notification(new EmailBounceNotification($this->invitation->company->account))->ninja();
} }
// { // {

View File

@ -11,17 +11,19 @@
namespace App\Listeners\User; namespace App\Listeners\User;
use App\Jobs\Mail\NinjaMailerJob; use App\Utils\Ninja;
use App\Jobs\Mail\NinjaMailerObject;
use App\Jobs\Util\SystemLogger;
use App\Libraries\MultiDB;
use App\Mail\User\UserLoggedIn;
use App\Models\SystemLog; use App\Models\SystemLog;
use Illuminate\Broadcasting\InteractsWithSockets; use App\Libraries\MultiDB;
use App\Jobs\Util\SystemLogger;
use App\Mail\User\UserLoggedIn;
use App\Jobs\Mail\NinjaMailerJob;
use Illuminate\Support\Facades\App;
use App\Jobs\Mail\NinjaMailerObject;
use Illuminate\Support\Facades\Cache;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels; use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Support\Facades\Cache;
class UpdateUserLastLogin implements ShouldQueue class UpdateUserLastLogin implements ShouldQueue
{ {
@ -46,6 +48,11 @@ class UpdateUserLastLogin implements ShouldQueue
{ {
MultiDB::setDb($event->company->db); MultiDB::setDb($event->company->db);
App::forgetInstance('translator');
$t = app('translator');
$t->replace(Ninja::transformTranslations($event->company->settings));
App::setLocale($event->company->locale());
$user = $event->user; $user = $event->user;
$user->last_login = now(); $user->last_login = now();
$user->save(); $user->save();

View File

@ -42,7 +42,6 @@ class VerifyUserObject
if($this->is_react) { if($this->is_react) {
$react_redirect = '?react=true'; $react_redirect = '?react=true';
nlog("is react");
} }
$data = [ $data = [

View File

@ -21,11 +21,9 @@ class EmailBounceNotification extends Notification
* *
* @return void * @return void
*/ */
protected $account;
public function __construct($account) public function __construct(private string $email_address)
{ {
$this->account = $account;
} }
/** /**
@ -64,11 +62,7 @@ class EmailBounceNotification extends Notification
public function toSlack($notifiable) public function toSlack($notifiable)
{ {
$content = "Email bounce notification for Account {$this->account->key} \n"; $content = "Email bounce notification for {$this->email_address} \n";
$owner = $this->account->companies()->first()->owner();
$content .= "Owner {$owner->present()->name() } | {$owner->email}";
return (new SlackMessage) return (new SlackMessage)
->success() ->success()

View File

@ -68,6 +68,7 @@ class BankIntegrationTransformer extends EntityTransformer
'created_at' => (int) $bank_integration->created_at, 'created_at' => (int) $bank_integration->created_at,
'updated_at' => (int) $bank_integration->updated_at, 'updated_at' => (int) $bank_integration->updated_at,
'archived_at' => (int) $bank_integration->deleted_at, 'archived_at' => (int) $bank_integration->deleted_at,
'integration_type' => (string) $bank_integration->integration_type ?: '',
]; ];
} }

View File

@ -5227,23 +5227,23 @@ $lang = array(
'primary_contact' => 'Primary Contact', 'primary_contact' => 'Primary Contact',
'all_contacts' => 'All Contacts', 'all_contacts' => 'All Contacts',
'insert_below' => 'Insert Below', 'insert_below' => 'Insert Below',
'nordigen_handler_subtitle' => 'will gain access for your selected bank account. After selecting your institution you are redirected to theire front-page to complete the request with your account credentials.', 'nordigen_handler_subtitle' => 'Bank account authentication. Selecting your institution to complete the request with your account credentials.',
'nordigen_handler_error_heading_unknown' => 'An Error has occured', 'nordigen_handler_error_heading_unknown' => 'An error has occured',
'nordigen_handler_error_contents_unknown' => 'An unknown Error has occured! Reason:', 'nordigen_handler_error_contents_unknown' => 'An unknown error has occurred! Reason:',
'nordigen_handler_error_heading_token_invalid' => 'Invalid Token', 'nordigen_handler_error_heading_token_invalid' => 'Invalid Token',
'nordigen_handler_error_contents_token_invalid' => 'The provided token was invalid. Please restart the flow, with a valid one_time_token. Contact support for help, if this issue persists.', 'nordigen_handler_error_contents_token_invalid' => 'The provided token was invalid. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_account_config_invalid' => 'Missing Credentials', 'nordigen_handler_error_heading_account_config_invalid' => 'Missing Credentials',
'nordigen_handler_error_contents_account_config_invalid' => 'The provided credentials for nordigen are eighter missing or invalid. Contact support for help, if this issue persists.', 'nordigen_handler_error_contents_account_config_invalid' => 'Invalid or missing credentials for Gocardless Bank Account Data. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_not_available' => 'Not Available', 'nordigen_handler_error_heading_not_available' => 'Not Available',
'nordigen_handler_error_contents_not_available' => 'This flow is not available for your account. Considder upgrading to enterprise version. Contact support for help, if this issue persists.', 'nordigen_handler_error_contents_not_available' => 'Feature unavailable, enterprise plan only.',
'nordigen_handler_error_heading_institution_invalid' => 'Invalid Institution', 'nordigen_handler_error_heading_institution_invalid' => 'Invalid Institution',
'nordigen_handler_error_contents_institution_invalid' => 'The provided institution-id is invalid or no longer valid. You can go to the bank selection page by clicking the button below or cancel the flow by clicking on the \'X\' above.', 'nordigen_handler_error_contents_institution_invalid' => 'The provided institution-id is invalid or no longer valid.',
'nordigen_handler_error_heading_ref_invalid' => 'Invalid Reference', 'nordigen_handler_error_heading_ref_invalid' => 'Invalid Reference',
'nordigen_handler_error_contents_ref_invalid' => 'Nordigen did not provide a valid reference. Please run flow again and contact support, if this issue persists.', 'nordigen_handler_error_contents_ref_invalid' => 'GoCardless did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_not_found' => 'Invalid Requisition', 'nordigen_handler_error_heading_not_found' => 'Invalid Requisition',
'nordigen_handler_error_contents_not_found' => 'Nordigen did not provide a valid reference. Please run flow again and contact support, if this issue persists.', 'nordigen_handler_error_contents_not_found' => 'GoCardless did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready', 'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You may called this site to early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.', 'nordigen_handler_error_contents_requisition_invalid_status' => 'You called this site too early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected', 'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.', 'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.', 'nordigen_handler_restart' => 'Restart flow.',

View File

@ -3364,7 +3364,7 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'credit_number_counter' => 'Compteur du numéro de crédit', 'credit_number_counter' => 'Compteur du numéro de crédit',
'reset_counter_date' => 'Réinitialiser le compteur de date', 'reset_counter_date' => 'Réinitialiser le compteur de date',
'counter_padding' => 'Espacement du compteur', 'counter_padding' => 'Espacement du compteur',
'shared_invoice_quote_counter' => 'Share Invoice/Quote Counter', 'shared_invoice_quote_counter' => 'Partager le compteur des factures/soumissions',
'default_tax_name_1' => 'Nom de taxe par défaut 1', 'default_tax_name_1' => 'Nom de taxe par défaut 1',
'default_tax_rate_1' => 'Taux de taxe par défaut 1', 'default_tax_rate_1' => 'Taux de taxe par défaut 1',
'default_tax_name_2' => 'Nom de taxe par défaut 2', 'default_tax_name_2' => 'Nom de taxe par défaut 2',
@ -3849,308 +3849,308 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'registration_url' => 'URL d\'inscription', 'registration_url' => 'URL d\'inscription',
'show_product_cost' => 'Afficher le montant du produit', 'show_product_cost' => 'Afficher le montant du produit',
'complete' => 'Terminé', 'complete' => 'Terminé',
'next' => 'Suivant', 'next' => 'Suivant',
'next_step' => 'Étape suivante', 'next_step' => 'Étape suivante',
'notification_credit_sent_subject' => 'le crédit :invoice a été envoyé à :client', 'notification_credit_sent_subject' => 'le crédit :invoice a été envoyé à :client',
'notification_credit_viewed_subject' => 'Le crédit :invoice a été consulté par :client', 'notification_credit_viewed_subject' => 'Le crédit :invoice a été consulté par :client',
'notification_credit_sent' => 'Un crédit de :amount a été envoyé par courriel au client :client.', 'notification_credit_sent' => 'Un crédit de :amount a été envoyé par courriel au client :client.',
'notification_credit_viewed' => 'Un crédit de :amount a été consulté par le client :client.', 'notification_credit_viewed' => 'Un crédit de :amount a été consulté par le client :client.',
'reset_password_text' => 'Saisissez votre adresse courriel pour réinitialiser votre mot de passe.', 'reset_password_text' => 'Saisissez votre adresse courriel pour réinitialiser votre mot de passe.',
'password_reset' => 'Réinitialisation du mot de passe', 'password_reset' => 'Réinitialisation du mot de passe',
'account_login_text' => 'Bienvenue ! Heureux de vous voir.', 'account_login_text' => 'Bienvenue ! Heureux de vous voir.',
'request_cancellation' => 'Annuler la demande', 'request_cancellation' => 'Annuler la demande',
'delete_payment_method' => 'Supprimer le mode de paiement', 'delete_payment_method' => 'Supprimer le mode de paiement',
'about_to_delete_payment_method' => 'Le mode de paiement sera supprimé', 'about_to_delete_payment_method' => 'Le mode de paiement sera supprimé',
'action_cant_be_reversed' => 'Cette action ne peut être annulée', 'action_cant_be_reversed' => 'Cette action ne peut être annulée',
'profile_updated_successfully' => 'Le profil a été mis à jour', 'profile_updated_successfully' => 'Le profil a été mis à jour',
'currency_ethiopian_birr' => 'birr éthiopien', 'currency_ethiopian_birr' => 'birr éthiopien',
'client_information_text' => 'Adresse permanente où vous recevez le courriel', 'client_information_text' => 'Adresse permanente où vous recevez le courriel',
'status_id' => 'État de facture', 'status_id' => 'État de facture',
'email_already_register' => 'Cette adresse courriel est déjà liée à un compte', 'email_already_register' => 'Cette adresse courriel est déjà liée à un compte',
'locations' => 'Emplacements', 'locations' => 'Emplacements',
'freq_indefinitely' => 'Indéfiniment', 'freq_indefinitely' => 'Indéfiniment',
'cycles_remaining' => 'Cycles restants', 'cycles_remaining' => 'Cycles restants',
'i_understand_delete' => 'Je comprends. Supprimer.', 'i_understand_delete' => 'Je comprends. Supprimer.',
'download_files' => 'Télécharger les fichiers', 'download_files' => 'Télécharger les fichiers',
'download_timeframe' => 'Utilisez ce lien pour télécharger vos fichiers. Le lien expirera dans 1 heure.', 'download_timeframe' => 'Utilisez ce lien pour télécharger vos fichiers. Le lien expirera dans 1 heure.',
'new_signup' => 'Nouvelle inscription', 'new_signup' => 'Nouvelle inscription',
'new_signup_text' => 'Un nouveau compte a été créé par :user - :email - de l\'adresse IP :ip', 'new_signup_text' => 'Un nouveau compte a été créé par :user - :email - de l\'adresse IP :ip',
'notification_payment_paid_subject' => 'Le paiement a été fait par :client', 'notification_payment_paid_subject' => 'Le paiement a été fait par :client',
'notification_partial_payment_paid_subject' => 'Le paiement partiel a été fait par :client', 'notification_partial_payment_paid_subject' => 'Le paiement partiel a été fait par :client',
'notification_payment_paid' => 'Un paiement de :amount a été fait par le client : pour la facture :invoice', 'notification_payment_paid' => 'Un paiement de :amount a été fait par le client : pour la facture :invoice',
'notification_partial_payment_paid' => 'Un paiement partiel de :amount a été fait par le client : pour la facture :invoice', 'notification_partial_payment_paid' => 'Un paiement partiel de :amount a été fait par le client : pour la facture :invoice',
'notification_bot' => 'Bot de notifications', 'notification_bot' => 'Bot de notifications',
'invoice_number_placeholder' => 'Facture N° :invoice', 'invoice_number_placeholder' => 'Facture N° :invoice',
'entity_number_placeholder' => ':entity N° :entity_number', 'entity_number_placeholder' => ':entity N° :entity_number',
'email_link_not_working' => 'Si le bouton ci-dessus ne fonctionne pas correctement, cliquez sur le lien', 'email_link_not_working' => 'Si le bouton ci-dessus ne fonctionne pas correctement, cliquez sur le lien',
'display_log' => 'Afficher le registre', 'display_log' => 'Afficher le registre',
'send_fail_logs_to_our_server' => 'Rapporter les erreurs en temps réel', 'send_fail_logs_to_our_server' => 'Rapporter les erreurs en temps réel',
'setup' => 'Configuration', 'setup' => 'Configuration',
'quick_overview_statistics' => 'Aperçu et statistiques', 'quick_overview_statistics' => 'Aperçu et statistiques',
'update_your_personal_info' => 'Mettre à jour vos infos personnelles', 'update_your_personal_info' => 'Mettre à jour vos infos personnelles',
'name_website_logo' => 'Nom, site web et logo', 'name_website_logo' => 'Nom, site web et logo',
'make_sure_use_full_link' => 'Utilisez le lien complet vers votre site', 'make_sure_use_full_link' => 'Utilisez le lien complet vers votre site',
'personal_address' => 'Adresse personnelle', 'personal_address' => 'Adresse personnelle',
'enter_your_personal_address' => 'Saisissez votre adresse personnelle', 'enter_your_personal_address' => 'Saisissez votre adresse personnelle',
'enter_your_shipping_address' => 'Saisissez votre adresse de livraison', 'enter_your_shipping_address' => 'Saisissez votre adresse de livraison',
'list_of_invoices' => 'Liste des factures', 'list_of_invoices' => 'Liste des factures',
'with_selected' => 'Avec la sélection de', 'with_selected' => 'Avec la sélection de',
'invoice_still_unpaid' => 'Cette facture est toujours impayée. Cliquez sur le bouton pour compléter le paiement', 'invoice_still_unpaid' => 'Cette facture est toujours impayée. Cliquez sur le bouton pour compléter le paiement',
'list_of_recurring_invoices' => 'Liste des factures récurrentes', 'list_of_recurring_invoices' => 'Liste des factures récurrentes',
'details_of_recurring_invoice' => 'Détails à propos des factures récurrentes', 'details_of_recurring_invoice' => 'Détails à propos des factures récurrentes',
'cancellation' => 'Annulation', 'cancellation' => 'Annulation',
'about_cancellation' => 'Pour cesser la facturation récurrente, cliquez sur la requête d\'annulation.', 'about_cancellation' => 'Pour cesser la facturation récurrente, cliquez sur la requête d\'annulation.',
'cancellation_warning' => 'Avertissement! Vous avez demandé une annulation de ce service. Votre service pourrait être annulé sans autre notification.', 'cancellation_warning' => 'Avertissement! Vous avez demandé une annulation de ce service. Votre service pourrait être annulé sans autre notification.',
'cancellation_pending' => 'Annulation en attente. Nous vous tiendrons au courant.', 'cancellation_pending' => 'Annulation en attente. Nous vous tiendrons au courant.',
'list_of_payments' => 'Liste des paiements', 'list_of_payments' => 'Liste des paiements',
'payment_details' => 'Détails du paiement', 'payment_details' => 'Détails du paiement',
'list_of_payment_invoices' => 'Liste des factures affectées par le paiement', 'list_of_payment_invoices' => 'Liste des factures affectées par le paiement',
'list_of_payment_methods' => 'Liste des modes de paiement', 'list_of_payment_methods' => 'Liste des modes de paiement',
'payment_method_details' => 'Détails du mode de paiement', 'payment_method_details' => 'Détails du mode de paiement',
'permanently_remove_payment_method' => 'Supprimer de façon définitive ce mode de paiement', 'permanently_remove_payment_method' => 'Supprimer de façon définitive ce mode de paiement',
'warning_action_cannot_be_reversed' => 'Avertissement! Cette action ne peut être annulée!', 'warning_action_cannot_be_reversed' => 'Avertissement! Cette action ne peut être annulée!',
'confirmation' => 'Confirmation', 'confirmation' => 'Confirmation',
'list_of_quotes' => 'Soumissions', 'list_of_quotes' => 'Soumissions',
'waiting_for_approval' => 'En attente d\'approbation', 'waiting_for_approval' => 'En attente d\'approbation',
'quote_still_not_approved' => 'Cette soumission n\'a pas encore été approuvée', 'quote_still_not_approved' => 'Cette soumission n\'a pas encore été approuvée',
'list_of_credits' => 'Crédits', 'list_of_credits' => 'Crédits',
'required_extensions' => 'Extensions requises', 'required_extensions' => 'Extensions requises',
'php_version' => 'Version PHP', 'php_version' => 'Version PHP',
'writable_env_file' => 'Fichier .env inscriptible', 'writable_env_file' => 'Fichier .env inscriptible',
'env_not_writable' => 'Le fichier .env n\'est pas inscriptible par l\'utilisateur en cours', 'env_not_writable' => 'Le fichier .env n\'est pas inscriptible par l\'utilisateur en cours',
'minumum_php_version' => 'Version PHP minimale', 'minumum_php_version' => 'Version PHP minimale',
'satisfy_requirements' => 'Assurez-vous que toutes les exigences sont satisfaites', 'satisfy_requirements' => 'Assurez-vous que toutes les exigences sont satisfaites',
'oops_issues' => 'Oups, quelque chose cloche !', 'oops_issues' => 'Oups, quelque chose cloche !',
'open_in_new_tab' => 'Ouvrir dans un nouvel onglet', 'open_in_new_tab' => 'Ouvrir dans un nouvel onglet',
'complete_your_payment' => 'Paiement complet', 'complete_your_payment' => 'Paiement complet',
'authorize_for_future_use' => 'Autoriser ce mode de paiement pour usage ultérieur', 'authorize_for_future_use' => 'Autoriser ce mode de paiement pour usage ultérieur',
'page' => 'Page', 'page' => 'Page',
'per_page' => 'Par page', 'per_page' => 'Par page',
'of' => 'De', 'of' => 'De',
'view_credit' => 'Voir le crédit', 'view_credit' => 'Voir le crédit',
'to_view_entity_password' => 'Pour voir :entity, vous devez saisir votre mot de passe.', 'to_view_entity_password' => 'Pour voir :entity, vous devez saisir votre mot de passe.',
'showing_x_of' => 'Affiche :first de :last de :total résultats', 'showing_x_of' => 'Affiche :first de :last de :total résultats',
'no_results' => 'Aucun résultat', 'no_results' => 'Aucun résultat',
'payment_failed_subject' => 'Le paiement a échoué pour le client :client', 'payment_failed_subject' => 'Le paiement a échoué pour le client :client',
'payment_failed_body' => 'Un paiement fait par le client :client a échoué avec le message :message', 'payment_failed_body' => 'Un paiement fait par le client :client a échoué avec le message :message',
'register' => 'S\'inscrire', 'register' => 'S\'inscrire',
'register_label' => 'Créer votre compte en quelques secondes', 'register_label' => 'Créer votre compte en quelques secondes',
'password_confirmation' => 'Confirmer votre mot de passe', 'password_confirmation' => 'Confirmer votre mot de passe',
'verification' => 'Vérification', 'verification' => 'Vérification',
'complete_your_bank_account_verification' => 'Avant d\'utiliser un compte bancaire, il doit être vérifié.', 'complete_your_bank_account_verification' => 'Avant d\'utiliser un compte bancaire, il doit être vérifié.',
'checkout_com' => 'Checkout.com', 'checkout_com' => 'Checkout.com',
'footer_label' => 'Tous droits réservés © :year :company.', 'footer_label' => 'Tous droits réservés © :year :company.',
'credit_card_invalid' => 'Le numéro de carte de crédit fourni n\'est pas valide', 'credit_card_invalid' => 'Le numéro de carte de crédit fourni n\'est pas valide',
'month_invalid' => 'Le mois indiqué n\'est pas valide', 'month_invalid' => 'Le mois indiqué n\'est pas valide',
'year_invalid' => 'L\'année indiquée n\'est pas valide', 'year_invalid' => 'L\'année indiquée n\'est pas valide',
'https_required' => 'HTTPS est requis, l\'envoi du formulaire va échouer', 'https_required' => 'HTTPS est requis, l\'envoi du formulaire va échouer',
'if_you_need_help' => 'Si vous avez besoin d\'aide, vous pouvez écrire à notre', 'if_you_need_help' => 'Si vous avez besoin d\'aide, vous pouvez écrire à notre',
'update_password_on_confirm' => 'Après la mise à jour du mot de passe, votre compte sera confirmé.', 'update_password_on_confirm' => 'Après la mise à jour du mot de passe, votre compte sera confirmé.',
'bank_account_not_linked' => 'Pour payer avec un compte bancaire, vous devez d\'abord l\'ajouter comme un mode de paiement.', 'bank_account_not_linked' => 'Pour payer avec un compte bancaire, vous devez d\'abord l\'ajouter comme un mode de paiement.',
'application_settings_label' => 'Enregistrons les informations de base sur votre Ninja de la facture!', 'application_settings_label' => 'Enregistrons les informations de base sur votre Ninja de la facture!',
'recommended_in_production' => 'Fortement recommandé en mode production', 'recommended_in_production' => 'Fortement recommandé en mode production',
'enable_only_for_development' => 'Activer seulement en mode développement', 'enable_only_for_development' => 'Activer seulement en mode développement',
'test_pdf' => 'Tester le PDF', 'test_pdf' => 'Tester le PDF',
'checkout_authorize_label' => 'Checkout.com peut être enregistrer comme un mode de paiement pour usage ultérieur, lors de la première transaction. Cochez "Enregistrer les infos de carte de crédit" lors du processus de paiement.', 'checkout_authorize_label' => 'Checkout.com peut être enregistrer comme un mode de paiement pour usage ultérieur, lors de la première transaction. Cochez "Enregistrer les infos de carte de crédit" lors du processus de paiement.',
'sofort_authorize_label' => 'Le compte bancaire (SOFORT) peut être enregistré comme un mode de paiement pour usage ultérieur, lors de la première transaction. Cochez "Enregistrer les infos de paiement" lors du processus de paiement.', 'sofort_authorize_label' => 'Le compte bancaire (SOFORT) peut être enregistré comme un mode de paiement pour usage ultérieur, lors de la première transaction. Cochez "Enregistrer les infos de paiement" lors du processus de paiement.',
'node_status' => 'État du noeud', 'node_status' => 'État du noeud',
'npm_status' => 'État du NPM', 'npm_status' => 'État du NPM',
'node_status_not_found' => 'Nœud introuvable. Est-il installé ?', 'node_status_not_found' => 'Nœud introuvable. Est-il installé ?',
'npm_status_not_found' => 'NPM introuvable. Est-il installé ?', 'npm_status_not_found' => 'NPM introuvable. Est-il installé ?',
'locked_invoice' => 'La facture est verrouillée et ne peut être modifiée', 'locked_invoice' => 'La facture est verrouillée et ne peut être modifiée',
'downloads' => 'Téléchargements', 'downloads' => 'Téléchargements',
'resource' => 'Ressource', 'resource' => 'Ressource',
'document_details' => 'Détails du document', 'document_details' => 'Détails du document',
'hash' => 'Hash', 'hash' => 'Hash',
'resources' => 'Ressources', 'resources' => 'Ressources',
'allowed_file_types' => 'Types de fichiers autorisés:', 'allowed_file_types' => 'Types de fichiers autorisés:',
'common_codes' => 'Codes communs et leurs significations', 'common_codes' => 'Codes communs et leurs significations',
'payment_error_code_20087' => '20087 : Données de suivi invalides (CVV et/ou date d\'expiration non valables)', 'payment_error_code_20087' => '20087 : Données de suivi invalides (CVV et/ou date d\'expiration non valables)',
'download_selected' => 'Télécharger la sélection', 'download_selected' => 'Télécharger la sélection',
'to_pay_invoices' => 'Pour payer les factures, vous devez', 'to_pay_invoices' => 'Pour payer les factures, vous devez',
'add_payment_method_first' => 'ajouter un mode de paiement', 'add_payment_method_first' => 'ajouter un mode de paiement',
'no_items_selected' => 'Aucun article sélectionné', 'no_items_selected' => 'Aucun article sélectionné',
'payment_due' => 'Paiement dû', 'payment_due' => 'Paiement dû',
'account_balance' => 'Solde de compte', 'account_balance' => 'Solde de compte',
'thanks' => 'Merci', 'thanks' => 'Merci',
'minimum_required_payment' => 'Le paiement minimum requis est :amount', 'minimum_required_payment' => 'Le paiement minimum requis est :amount',
'under_payments_disabled' => 'L\'entreprise d\'autorise pas les surpaiements.', 'under_payments_disabled' => 'L\'entreprise d\'autorise pas les surpaiements.',
'over_payments_disabled' => 'L\'entreprise d\'autorise pas les souspaiements.', 'over_payments_disabled' => 'L\'entreprise d\'autorise pas les souspaiements.',
'saved_at' => 'Enregistré à :time', 'saved_at' => 'Enregistré à :time',
'credit_payment' => 'Le crédit a été appliqué à la facture :invoice_number', 'credit_payment' => 'Le crédit a été appliqué à la facture :invoice_number',
'credit_subject' => 'Nouveau crédit :credit de :account', 'credit_subject' => 'Nouveau crédit :credit de :account',
'credit_message' => 'Pour voir le crédit de :amount, cliquez sur le lien ci-dessous.', 'credit_message' => 'Pour voir le crédit de :amount, cliquez sur le lien ci-dessous.',
'payment_type_Crypto' => 'Cryptodevise', 'payment_type_Crypto' => 'Cryptodevise',
'payment_type_Credit' => 'Crédit', 'payment_type_Credit' => 'Crédit',
'store_for_future_use' => 'Enregistrer pour un usage ultérieur', 'store_for_future_use' => 'Enregistrer pour un usage ultérieur',
'pay_with_credit' => 'Payer avec un crédit', 'pay_with_credit' => 'Payer avec un crédit',
'payment_method_saving_failed' => 'Ce mode de paiement ne peut pas être enregistré pour usage ultérieur.', 'payment_method_saving_failed' => 'Ce mode de paiement ne peut pas être enregistré pour usage ultérieur.',
'pay_with' => 'Payer avec', 'pay_with' => 'Payer avec',
'n/a' => 'N/D', 'n/a' => 'N/D',
'by_clicking_next_you_accept_terms' => 'En cliquant sur "Prochaine étape", vous acceptez les conditions.', 'by_clicking_next_you_accept_terms' => 'En cliquant sur "Prochaine étape", vous acceptez les conditions.',
'not_specified' => 'Non spécifié', 'not_specified' => 'Non spécifié',
'before_proceeding_with_payment_warning' => 'Avant de procéder au paiement, vous devez remplir les champs suivants', 'before_proceeding_with_payment_warning' => 'Avant de procéder au paiement, vous devez remplir les champs suivants',
'after_completing_go_back_to_previous_page' => 'Retournez à la page précédente après avoir complété', 'after_completing_go_back_to_previous_page' => 'Retournez à la page précédente après avoir complété',
'pay' => 'Payer', 'pay' => 'Payer',
'instructions' => 'Instructions', 'instructions' => 'Instructions',
'notification_invoice_reminder1_sent_subject' => 'Le rappel 1 pour la facture :invoice a été envoyé à :client', 'notification_invoice_reminder1_sent_subject' => 'Le rappel 1 pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder2_sent_subject' => 'Le rappel 2 pour la facture :invoice a été envoyé à :client', 'notification_invoice_reminder2_sent_subject' => 'Le rappel 2 pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder3_sent_subject' => 'Le rappel 3 pour la facture :invoice a été envoyé à :client', 'notification_invoice_reminder3_sent_subject' => 'Le rappel 3 pour la facture :invoice a été envoyé à :client',
'notification_invoice_custom_sent_subject' => 'Le rappel personnalisé pour la facture :invoice a été envoyé à :client', 'notification_invoice_custom_sent_subject' => 'Le rappel personnalisé pour la facture :invoice a été envoyé à :client',
'notification_invoice_reminder_endless_sent_subject' => 'Un rappel perpétuel pour la facture :invoice a été envoyé à :client', 'notification_invoice_reminder_endless_sent_subject' => 'Un rappel perpétuel pour la facture :invoice a été envoyé à :client',
'assigned_user' => 'Utilisateur affecté', 'assigned_user' => 'Utilisateur affecté',
'setup_steps_notice' => 'Pour accéder à la prochaine étape, vous devez tester chaque section.', 'setup_steps_notice' => 'Pour accéder à la prochaine étape, vous devez tester chaque section.',
'setup_phantomjs_note' => 'Notes à propos de Phantom JS. En savoir plus.', 'setup_phantomjs_note' => 'Notes à propos de Phantom JS. En savoir plus.',
'minimum_payment' => 'Paiement minimum', 'minimum_payment' => 'Paiement minimum',
'no_action_provided' => 'Aucune action reçue. Si cest une erreur, veuillez contacter le soutien technique.', 'no_action_provided' => 'Aucune action reçue. Si cest une erreur, veuillez contacter le soutien technique.',
'no_payable_invoices_selected' => 'Aucune des factures sélectionnées porte un solde dû. Assurez-vous que vous n\'essayez pas de payer une facture provisoire ou une facture dont le solde est nul.', 'no_payable_invoices_selected' => 'Aucune des factures sélectionnées porte un solde dû. Assurez-vous que vous n\'essayez pas de payer une facture provisoire ou une facture dont le solde est nul.',
'required_payment_information' => 'Détails de paiement requis', 'required_payment_information' => 'Détails de paiement requis',
'required_payment_information_more' => 'Pour terminer le paiement, nous avons besoin de plus d\'informations à propos de vous.', 'required_payment_information_more' => 'Pour terminer le paiement, nous avons besoin de plus d\'informations à propos de vous.',
'required_client_info_save_label' => 'Ces informations seront sauvegardées. Vous n\'aurez pas à les saisir la prochaine fois.', 'required_client_info_save_label' => 'Ces informations seront sauvegardées. Vous n\'aurez pas à les saisir la prochaine fois.',
'notification_credit_bounced' => 'Nous n\'avons pas pu émettre de Credit :invoice to :contact. \n :error', 'notification_credit_bounced' => 'Nous n\'avons pas pu émettre de Credit :invoice to :contact. \n :error',
'notification_credit_bounced_subject' => 'Impossible d\'émettre Crédit :invoice', 'notification_credit_bounced_subject' => 'Impossible d\'émettre Crédit :invoice',
'save_payment_method_details' => 'Enregistrer les infos de mode de paiement', 'save_payment_method_details' => 'Enregistrer les infos de mode de paiement',
'new_card' => 'Nouvelle carte', 'new_card' => 'Nouvelle carte',
'new_bank_account' => 'Nouveau compte bancaire', 'new_bank_account' => 'Nouveau compte bancaire',
'company_limit_reached' => 'Limite de :limit entreprises par compte.', 'company_limit_reached' => 'Limite de :limit entreprises par compte.',
'credits_applied_validation' => 'Le total des crédits octroyés ne peut être supérieur au total des factures', 'credits_applied_validation' => 'Le total des crédits octroyés ne peut être supérieur au total des factures',
'credit_number_taken' => 'Ce numéro de crédit est déjà utilisé', 'credit_number_taken' => 'Ce numéro de crédit est déjà utilisé',
'credit_not_found' => 'Crédit introuvable', 'credit_not_found' => 'Crédit introuvable',
'invoices_dont_match_client' => 'Les factures sélectionnées proviennent de plus d\'un client', 'invoices_dont_match_client' => 'Les factures sélectionnées proviennent de plus d\'un client',
'duplicate_credits_submitted' => 'Crédits soumis en double.', 'duplicate_credits_submitted' => 'Crédits soumis en double.',
'duplicate_invoices_submitted' => 'Factures soumises en double.', 'duplicate_invoices_submitted' => 'Factures soumises en double.',
'credit_with_no_invoice' => 'Vous devez avoir une facture en règle avant de pouvoir utiliser un crédit lors d\'un paiement', 'credit_with_no_invoice' => 'Vous devez avoir une facture en règle avant de pouvoir utiliser un crédit lors d\'un paiement',
'client_id_required' => 'Le numéro d\'identification du client est requis', 'client_id_required' => 'Le numéro d\'identification du client est requis',
'expense_number_taken' => 'Numéro de remboursement déjà utilisé', 'expense_number_taken' => 'Numéro de remboursement déjà utilisé',
'invoice_number_taken' => 'Numéro de facture déjà utilisé', 'invoice_number_taken' => 'Numéro de facture déjà utilisé',
'payment_id_required' => 'Numéro de paiement requis.', 'payment_id_required' => 'Numéro de paiement requis.',
'unable_to_retrieve_payment' => 'Impossible de récupérer le numéro de paiement spécifié', 'unable_to_retrieve_payment' => 'Impossible de récupérer le numéro de paiement spécifié',
'invoice_not_related_to_payment' => 'La facture #:invoice n\'est pas liée à ce paiement', 'invoice_not_related_to_payment' => 'La facture #:invoice n\'est pas liée à ce paiement',
'credit_not_related_to_payment' => 'Le crédit #:credit n\'est pas lié à ce paiement', 'credit_not_related_to_payment' => 'Le crédit #:credit n\'est pas lié à ce paiement',
'max_refundable_invoice' => 'Essai de remboursement plus élevé que permis pour la facture #:invoice. Le maximum remboursable est :amount.', 'max_refundable_invoice' => 'Essai de remboursement plus élevé que permis pour la facture #:invoice. Le maximum remboursable est :amount.',
'refund_without_invoices' => 'Essai de remboursement d\'un paiement avec factures jointes. Veuillez spécifier une ou des factures valides à rembourser.', 'refund_without_invoices' => 'Essai de remboursement d\'un paiement avec factures jointes. Veuillez spécifier une ou des factures valides à rembourser.',
'refund_without_credits' => 'Essai de remboursement d\'un paiement avec crédits jointes. Veuillez spécifier un ou des crédits valides à rembourser.', 'refund_without_credits' => 'Essai de remboursement d\'un paiement avec crédits jointes. Veuillez spécifier un ou des crédits valides à rembourser.',
'max_refundable_credit' => 'Essai de remboursement plus élevé que permis pour le crédit :credit. Le maximum remboursable est :amount.', 'max_refundable_credit' => 'Essai de remboursement plus élevé que permis pour le crédit :credit. Le maximum remboursable est :amount.',
'project_client_do_not_match' => 'Partiellement non-appliquée', 'project_client_do_not_match' => 'Partiellement non-appliquée',
'quote_number_taken' => 'Ce numéro de soumission est déjà pris', 'quote_number_taken' => 'Ce numéro de soumission est déjà pris',
'recurring_invoice_number_taken' => 'Le numéro de facture récurrente :number est déjà pris', 'recurring_invoice_number_taken' => 'Le numéro de facture récurrente :number est déjà pris',
'user_not_associated_with_account' => 'L\'utilisateur n\'est pas associé à ce compte', 'user_not_associated_with_account' => 'L\'utilisateur n\'est pas associé à ce compte',
'amounts_do_not_balance' => 'Les montants ne balancent pas correctement.', 'amounts_do_not_balance' => 'Les montants ne balancent pas correctement.',
'insufficient_applied_amount_remaining' => 'Montant restant affecté insuffisant pour couvrir ce paiement.', 'insufficient_applied_amount_remaining' => 'Montant restant affecté insuffisant pour couvrir ce paiement.',
'insufficient_credit_balance' => 'Solde insuffisant sur le crédit', 'insufficient_credit_balance' => 'Solde insuffisant sur le crédit',
'one_or_more_invoices_paid' => 'Une ou plusieurs factures ont été payées', 'one_or_more_invoices_paid' => 'Une ou plusieurs factures ont été payées',
'invoice_cannot_be_refunded' => 'La facture #:number ne peut être remboursée', 'invoice_cannot_be_refunded' => 'La facture #:number ne peut être remboursée',
'attempted_refund_failed' => 'Essai de remboursement du montant :amount seulement :refundable_amount  disponible pour remboursement.', 'attempted_refund_failed' => 'Essai de remboursement du montant :amount seulement :refundable_amount  disponible pour remboursement.',
'user_not_associated_with_this_account' => 'Cet utilisateur ne peut être rattaché à cette entreprise. Peut-être a-t-il déjà enregistré un utilisateur sur un autre compte?', 'user_not_associated_with_this_account' => 'Cet utilisateur ne peut être rattaché à cette entreprise. Peut-être a-t-il déjà enregistré un utilisateur sur un autre compte?',
'migration_completed' => 'Migration complétée', 'migration_completed' => 'Migration complétée',
'migration_completed_description' => 'La migration est complétée. Veuillez vérifier vos données après la connexion.', 'migration_completed_description' => 'La migration est complétée. Veuillez vérifier vos données après la connexion.',
'api_404' => '404 | Rien à voir ici!', 'api_404' => '404 | Rien à voir ici!',
'large_account_update_parameter' => 'Le chargement d\'un gros compte est impossible sans un paramètre updated_at', 'large_account_update_parameter' => 'Le chargement d\'un gros compte est impossible sans un paramètre updated_at',
'no_backup_exists' => 'Aucune sauvegarde n\'existe pour cette activité', 'no_backup_exists' => 'Aucune sauvegarde n\'existe pour cette activité',
'company_user_not_found' => 'L\'enregistrement de l\'entreprise de l\'utilisateur introuvable.', 'company_user_not_found' => 'L\'enregistrement de l\'entreprise de l\'utilisateur introuvable.',
'no_credits_found' => 'Aucun crédit trouvé.', 'no_credits_found' => 'Aucun crédit trouvé.',
'action_unavailable' => 'L\'action :action demandée n\'est pas disponible', 'action_unavailable' => 'L\'action :action demandée n\'est pas disponible',
'no_documents_found' => 'Aucun document trouvé', 'no_documents_found' => 'Aucun document trouvé',
'no_group_settings_found' => 'Aucun paramètre de groupe trouvé', 'no_group_settings_found' => 'Aucun paramètre de groupe trouvé',
'access_denied' => 'Permissions insuffisantes pour accéder/modifier cette ressource', 'access_denied' => 'Permissions insuffisantes pour accéder/modifier cette ressource',
'invoice_cannot_be_marked_paid' => 'La facture ne peut pas être marquée comme payée', 'invoice_cannot_be_marked_paid' => 'La facture ne peut pas être marquée comme payée',
'invoice_license_or_environment' => 'License invalide, ou environnement :environment invalide', 'invoice_license_or_environment' => 'License invalide, ou environnement :environment invalide',
'route_not_available' => 'La route n\'est pas disponible', 'route_not_available' => 'La route n\'est pas disponible',
'invalid_design_object' => 'Objet de modèle personnalisé invalide', 'invalid_design_object' => 'Objet de modèle personnalisé invalide',
'quote_not_found' => 'Soumission(s) introuvable(s)', 'quote_not_found' => 'Soumission(s) introuvable(s)',
'quote_unapprovable' => 'L\'approbation de cette soumission ne peut se faire puisqu\'elle est expirée.', 'quote_unapprovable' => 'L\'approbation de cette soumission ne peut se faire puisqu\'elle est expirée.',
'scheduler_has_run' => 'Le planificateur a démarré', 'scheduler_has_run' => 'Le planificateur a démarré',
'scheduler_has_never_run' => 'Le planificateur n\'a jamais démarré', 'scheduler_has_never_run' => 'Le planificateur n\'a jamais démarré',
'self_update_not_available' => 'La mise à jour manuelle n\'est pas disponible sur ce système', 'self_update_not_available' => 'La mise à jour manuelle n\'est pas disponible sur ce système',
'user_detached' => 'L\'utilisateur a été détaché de l\'entreprise', 'user_detached' => 'L\'utilisateur a été détaché de l\'entreprise',
'create_webhook_failure' => 'Création Webhook impossible', 'create_webhook_failure' => 'Création Webhook impossible',
'payment_message_extended' => 'Merci pour votre paiement d\'un montant de :amount', 'payment_message_extended' => 'Merci pour votre paiement d\'un montant de :amount',
'online_payments_minimum_note' => 'Note: Les paiements en ligne sont acceptés seulement si le montant est plus élevé que 1$ ou en devise équivalente.', 'online_payments_minimum_note' => 'Note: Les paiements en ligne sont acceptés seulement si le montant est plus élevé que 1$ ou en devise équivalente.',
'payment_token_not_found' => 'Le jeton de paiement est introuvable. Veuillez essayer de nouveau. Si le problème persiste, essayez avec un autre mode de paiement', 'payment_token_not_found' => 'Le jeton de paiement est introuvable. Veuillez essayer de nouveau. Si le problème persiste, essayez avec un autre mode de paiement',
'vendor_address1' => 'Rue du fournisseur', 'vendor_address1' => 'Rue du fournisseur',
'vendor_address2' => 'App du fournisseur', 'vendor_address2' => 'App du fournisseur',
'partially_unapplied' => 'Partiellement non-appliquée', 'partially_unapplied' => 'Partiellement non-appliquée',
'select_a_gmail_user' => 'Veuillez sélectionner un utilisateur authentifié avec Gmail', 'select_a_gmail_user' => 'Veuillez sélectionner un utilisateur authentifié avec Gmail',
'list_long_press' => 'Longue pression pour liste', 'list_long_press' => 'Longue pression pour liste',
'show_actions' => 'Afficher les actions', 'show_actions' => 'Afficher les actions',
'start_multiselect' => 'Démarrer la multisélection', 'start_multiselect' => 'Démarrer la multisélection',
'email_sent_to_confirm_email' => 'Un courriel a été envoyé pour confirmer l\'adresse courriel', 'email_sent_to_confirm_email' => 'Un courriel a été envoyé pour confirmer l\'adresse courriel',
'converted_paid_to_date' => 'Payé à ce jour converti', 'converted_paid_to_date' => 'Payé à ce jour converti',
'converted_credit_balance' => 'Solde de crédit converti', 'converted_credit_balance' => 'Solde de crédit converti',
'converted_total' => 'Total converti', 'converted_total' => 'Total converti',
'reply_to_name' => 'Répondre à', 'reply_to_name' => 'Répondre à',
'payment_status_-2' => 'Partiellement non-appliquée', 'payment_status_-2' => 'Partiellement non-appliquée',
'color_theme' => 'Couleur de thème', 'color_theme' => 'Couleur de thème',
'start_migration' => 'Démarrer la migration', 'start_migration' => 'Démarrer la migration',
'recurring_cancellation_request' => 'Demande d\'annulation de facture récurrente de :contact', 'recurring_cancellation_request' => 'Demande d\'annulation de facture récurrente de :contact',
'recurring_cancellation_request_body' => ':contact du client :client a demandé l\'annulation de la facture récurrente : invoice', 'recurring_cancellation_request_body' => ':contact du client :client a demandé l\'annulation de la facture récurrente : invoice',
'hello' => 'Bonjour', 'hello' => 'Bonjour',
'group_documents' => 'Grouper les documents', 'group_documents' => 'Grouper les documents',
'quote_approval_confirmation_label' => 'Êtes-vous certain de vouloir approuver cette soumission ?', 'quote_approval_confirmation_label' => 'Êtes-vous certain de vouloir approuver cette soumission ?',
'migration_select_company_label' => 'Sélectionnez les entreprises pour la migration', 'migration_select_company_label' => 'Sélectionnez les entreprises pour la migration',
'force_migration' => 'Forcer la migration', 'force_migration' => 'Forcer la migration',
'require_password_with_social_login' => 'Requiert un mot de passe avec une connexion de réseau social', 'require_password_with_social_login' => 'Requiert un mot de passe avec une connexion de réseau social',
'stay_logged_in' => 'Restez connecté', 'stay_logged_in' => 'Restez connecté',
'session_about_to_expire' => 'Avertissement: Votre session va expirer bientôt', 'session_about_to_expire' => 'Avertissement: Votre session va expirer bientôt',
'count_hours' => ':count heures', 'count_hours' => ':count heures',
'count_day' => '1 jour', 'count_day' => '1 jour',
'count_days' => ':count jours', 'count_days' => ':count jours',
'web_session_timeout' => 'Expiration de la session web', 'web_session_timeout' => 'Expiration de la session web',
'security_settings' => 'Paramètres de sécurité', 'security_settings' => 'Paramètres de sécurité',
'resend_email' => 'Renvoyer le courriel', 'resend_email' => 'Renvoyer le courriel',
'confirm_your_email_address' => 'Veuillez confirmer votre adresse courriel', 'confirm_your_email_address' => 'Veuillez confirmer votre adresse courriel',
'freshbooks' => 'FreshBooks', 'freshbooks' => 'FreshBooks',
'invoice2go' => 'Invoice2go', 'invoice2go' => 'Invoice2go',
'invoicely' => 'Invoicely', 'invoicely' => 'Invoicely',
'waveaccounting' => 'Wave Accounting', 'waveaccounting' => 'Wave Accounting',
'zoho' => 'Zoho', 'zoho' => 'Zoho',
'accounting' => 'Comptabilité', 'accounting' => 'Comptabilité',
'required_files_missing' => 'Veuillez fournir tous les CSV.', 'required_files_missing' => 'Veuillez fournir tous les CSV.',
'migration_auth_label' => 'Continuez en vous authentifiant.', 'migration_auth_label' => 'Continuez en vous authentifiant.',
'api_secret' => 'API secret', 'api_secret' => 'API secret',
'migration_api_secret_notice' => 'Vous pouvez trouver API_SECRET dans le fichier .env ou Invoice Ninja v5. Si la propriété est manquante, laissez le champ vide.', 'migration_api_secret_notice' => 'Vous pouvez trouver API_SECRET dans le fichier .env ou Invoice Ninja v5. Si la propriété est manquante, laissez le champ vide.',
'billing_coupon_notice' => 'Votre rabais sera appliqué au moment de régler votre facture.', 'billing_coupon_notice' => 'Votre rabais sera appliqué au moment de régler votre facture.',
'use_last_email' => 'Utiliser le dernier e-mail', 'use_last_email' => 'Utiliser le dernier e-mail',
'activate_company' => 'Activer l\'entreprise', 'activate_company' => 'Activer l\'entreprise',
'activate_company_help' => 'Activez les courriels, les factures récurrentes et les notifications', 'activate_company_help' => 'Activez les courriels, les factures récurrentes et les notifications',
'an_error_occurred_try_again' => 'Une erreur s\'est produite, veuillez réessayer', 'an_error_occurred_try_again' => 'Une erreur s\'est produite, veuillez réessayer',
'please_first_set_a_password' => 'Veuillez d\'abord définir un mot de passe', 'please_first_set_a_password' => 'Veuillez d\'abord définir un mot de passe',
'changing_phone_disables_two_factor' => 'Attention: modifier votre numéro de téléphone désactivera l\'authentification à deux facteurs 2FA', 'changing_phone_disables_two_factor' => 'Attention: modifier votre numéro de téléphone désactivera l\'authentification à deux facteurs 2FA',
'help_translate' => 'Aide à la traduction', 'help_translate' => 'Aide à la traduction',
'please_select_a_country' => 'Veuillez sélectionner un pays', 'please_select_a_country' => 'Veuillez sélectionner un pays',
'disabled_two_factor' => 'L\'authentification à deux facteurs 2FA a été désactivée', 'disabled_two_factor' => 'L\'authentification à deux facteurs 2FA a été désactivée',
'connected_google' => 'Le compte a été connecté', 'connected_google' => 'Le compte a été connecté',
'disconnected_google' => 'Le compte a été déconnecté', 'disconnected_google' => 'Le compte a été déconnecté',
'delivered' => 'Livré', 'delivered' => 'Livré',
'spam' => 'Pourriel', 'spam' => 'Pourriel',
'view_docs' => 'Afficher la documentation', 'view_docs' => 'Afficher la documentation',
'enter_phone_to_enable_two_factor' => 'Veuillez fournir un numéro de téléphone mobile pour activer l\'authentification à deux facteurs', 'enter_phone_to_enable_two_factor' => 'Veuillez fournir un numéro de téléphone mobile pour activer l\'authentification à deux facteurs',
'send_sms' => 'Envoyer un SMS', 'send_sms' => 'Envoyer un SMS',
'sms_code' => 'Code SMS', 'sms_code' => 'Code SMS',
'connect_google' => 'Connecter Google', 'connect_google' => 'Connecter Google',
'disconnect_google' => 'Déconnecter Google', 'disconnect_google' => 'Déconnecter Google',
'disable_two_factor' => 'Désactiver l\'authentification à deux facteurs', 'disable_two_factor' => 'Désactiver l\'authentification à deux facteurs',
'invoice_task_datelog' => 'Facturer le journal des dates des tâches', 'invoice_task_datelog' => 'Facturer le journal des dates des tâches',
'invoice_task_datelog_help' => 'Ajouter les détails de date aux lignes d\'articles des factures', 'invoice_task_datelog_help' => 'Ajouter les détails de date aux lignes d\'articles des factures',
'promo_code' => 'Code promo', 'promo_code' => 'Code promo',
'recurring_invoice_issued_to' => 'Facture récurrente émise à', 'recurring_invoice_issued_to' => 'Facture récurrente émise à',
'subscription' => 'Abonnement', 'subscription' => 'Abonnement',
'new_subscription' => 'Nouvel abonnement', 'new_subscription' => 'Nouvel abonnement',
'deleted_subscription' => 'L\'abonnement a été supprimé', 'deleted_subscription' => 'L\'abonnement a été supprimé',
'removed_subscription' => 'L\'abonnement a été retiré', 'removed_subscription' => 'L\'abonnement a été retiré',
'restored_subscription' => 'L\'abonnement a été restauré', 'restored_subscription' => 'L\'abonnement a été restauré',
'search_subscription' => 'Recherche de 1 abonnement', 'search_subscription' => 'Recherche de 1 abonnement',
'search_subscriptions' => 'Recherche :count abonnements', 'search_subscriptions' => 'Recherche :count abonnements',
'subdomain_is_not_available' => 'Le sous-domaine n\'est pas disponible', 'subdomain_is_not_available' => 'Le sous-domaine n\'est pas disponible',
'connect_gmail' => 'Connectez Gmail', 'connect_gmail' => 'Connectez Gmail',
'disconnect_gmail' => 'Déconnecter Gmail', 'disconnect_gmail' => 'Déconnecter Gmail',
'connected_gmail' => 'Gmail a été connecté', 'connected_gmail' => 'Gmail a été connecté',
'disconnected_gmail' => 'Gmail a été déconnecté', 'disconnected_gmail' => 'Gmail a été déconnecté',
'update_fail_help' => 'Les modifications apportées au code de base peuvent bloquer la mise à jour, vous pouvez exécuter cette commande pour annuler les modifications:', 'update_fail_help' => 'Les modifications apportées au code de base peuvent bloquer la mise à jour, vous pouvez exécuter cette commande pour annuler les modifications:',
'client_id_number' => 'Numéro d\'identification du client', 'client_id_number' => 'Numéro d\'identification du client',
'count_minutes' => ':count minutes', 'count_minutes' => ':count minutes',
'password_timeout' => 'Délai d\'expiration du mot de passe', 'password_timeout' => 'Délai d\'expiration du mot de passe',
'shared_invoice_credit_counter' => 'Partager le compteur pour les factures et les crédits', 'shared_invoice_credit_counter' => 'Partager le compteur pour les factures et les crédits',
'activity_80' => ':user a créé l\'abonnement :subscription', 'activity_80' => ':user a créé l\'abonnement :subscription',
'activity_81' => ':user a mis à jour l\'abonnement :subscription', 'activity_81' => ':user a mis à jour l\'abonnement :subscription',
'activity_82' => ':user a archivé l\'abonnement :subscription', 'activity_82' => ':user a archivé l\'abonnement :subscription',
@ -5212,6 +5212,34 @@ Lorsque les montant apparaîtront sur votre relevé, veuillez revenir sur cette
'receipt' => 'Reçu', 'receipt' => 'Reçu',
'charges' => 'Charges', 'charges' => 'Charges',
'email_report' => 'Envoyer le rapport', 'email_report' => 'Envoyer le rapport',
'payment_type_Pay Later' => 'Payer plus tard',
'payment_type_credit' => 'Type de paiement crédit',
'payment_type_debit' => 'Type de paiement débit',
'send_emails_to' => 'Envoyer les courriels à',
'primary_contact' => 'Contact principal',
'all_contacts' => 'Tous les contacts',
'insert_below' => 'Insérer ci-dessous',
'nordigen_handler_subtitle' => 'will gain access for your selected bank account. After selecting your institution you are redirected to theire front-page to complete the request with your account credentials.',
'nordigen_handler_error_heading_unknown' => 'An Error has occured',
'nordigen_handler_error_contents_unknown' => 'An unknown Error has occured! Reason:',
'nordigen_handler_error_heading_token_invalid' => 'Invalid Token',
'nordigen_handler_error_contents_token_invalid' => 'The provided token was invalid. Please restart the flow, with a valid one_time_token. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_account_config_invalid' => 'Missing Credentials',
'nordigen_handler_error_contents_account_config_invalid' => 'The provided credentials for nordigen are eighter missing or invalid. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_not_available' => 'Not Available',
'nordigen_handler_error_contents_not_available' => 'This flow is not available for your account. Considder upgrading to enterprise version. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_institution_invalid' => 'Invalid Institution',
'nordigen_handler_error_contents_institution_invalid' => 'The provided institution-id is invalid or no longer valid. You can go to the bank selection page by clicking the button below or cancel the flow by clicking on the \'X\' above.',
'nordigen_handler_error_heading_ref_invalid' => 'Invalid Reference',
'nordigen_handler_error_contents_ref_invalid' => 'Nordigen did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_not_found' => 'Invalid Requisition',
'nordigen_handler_error_contents_not_found' => 'Nordigen did not provide a valid reference. Please run flow again and contact support, if this issue persists.',
'nordigen_handler_error_heading_requisition_invalid_status' => 'Not Ready',
'nordigen_handler_error_contents_requisition_invalid_status' => 'You may called this site to early. Please finish authorization and refresh this page. Contact support for help, if this issue persists.',
'nordigen_handler_error_heading_requisition_no_accounts' => 'No Accounts selected',
'nordigen_handler_error_contents_requisition_no_accounts' => 'The service has not returned any valid accounts. Considder restarting the flow.',
'nordigen_handler_restart' => 'Restart flow.',
'nordigen_handler_return' => 'Return to application.',
); );
return $lang; return $lang;

View File

@ -11,8 +11,9 @@
namespace Tests\Unit\ValidationRules; namespace Tests\Unit\ValidationRules;
use App\Http\ValidationRules\Account\BlackListRule;
use Tests\TestCase; use Tests\TestCase;
use App\Http\ValidationRules\Account\BlackListRule;
use App\Http\ValidationRules\Account\EmailBlackListRule;
/** /**
* @test * @test
@ -25,6 +26,35 @@ class BlacklistValidationTest extends TestCase
parent::setUp(); parent::setUp();
} }
public function testValidEmailRule3()
{
$rules = [
'email' => [new EmailBlackListRule],
];
$data = [
'email' => 'contact@invoiceninja.com',
];
$v = $this->app['validator']->make($data, $rules);
$this->assertTrue($v->passes());
}
public function testValidEmailRule2()
{
$rules = [
'email' => [new EmailBlackListRule],
];
$data = [
'email' => 'noddy@invoiceninja.com',
];
$v = $this->app['validator']->make($data, $rules);
$this->assertFalse($v->passes());
}
public function testValidEmailRule() public function testValidEmailRule()
{ {
$rules = [ $rules = [
@ -52,4 +82,32 @@ class BlacklistValidationTest extends TestCase
$v = $this->app['validator']->make($data, $rules); $v = $this->app['validator']->make($data, $rules);
$this->assertFalse($v->passes()); $this->assertFalse($v->passes());
} }
public function testInValidEmailRule2()
{
$rules = [
'email' => [new BlackListRule],
];
$data = [
'email' => 'jimmy@zzz.com',
];
$v = $this->app['validator']->make($data, $rules);
$this->assertFalse($v->passes());
}
public function testInValidEmailRule3()
{
$rules = [
'email' => [new BlackListRule],
];
$data = [
'email' => 'jimmy@gmail.com',
];
$v = $this->app['validator']->make($data, $rules);
$this->assertTrue($v->passes());
}
} }