Before you start
Nothing on this page is required. The plugin is complete without a single line of code: install it, run the setup wizard, and it works. Every hook below is an optional extension point for developers. The settings page and the wizard cover everything a site owner normally wants: what an unconfirmed customer has to wait for, how long a link stays valid, the email text, the resend wait, exempt roles, and since 1.0.8 the page a customer sees after confirming. Look there first. Hooks are for the cases a setting cannot cover: a decision that depends on the user, a text that depends on the page, or telling another system what happened.
Where to put your code
In a small plugin of your own in wp-content/plugins/, or in a file in wp-content/mu-plugins/. Not in the theme's functions.php: a theme switch would silently drop it. A plugin file needs only a header:
<?php
/**
* Plugin Name: My site: Email Verify tweaks
*/
// Your add_filter() and add_action() calls go here.
How to read this page
- Filters let you change a value the plugin is about to use. Always return a value; return what you were given to change nothing.
- Actions tell you that something happened. They cannot change the outcome.
- Hooks marked since 1.0.8 need version 1.0.8 or later. Everything else exists since the first public release.
- The one-line signature under each heading shows the parameter types for reading; it is not code to paste. The Example block is.
- All hook names start with
wpcev_. Every parameter called$user_idis a WordPress user ID;get_userdata( $user_id )gives you the rest.
Three things to leave alone. Never log or store the plaintext $token some filters receive. Do not use a filter to wave a customer through a gate without a reason you can explain (the plugin's security depends on those gates). And when a hook hands you a $user_id of 0, it means the request proved nothing about who the user is, so do not personalise or write anything on it.
Who counts as confirmed
The plugin holds a user back when their account carries the flag "not confirmed". Users who registered before the plugin was activated and users in an exempt role are never held back. These hooks change that decision or ask for it.
wpcev_is_blocked filter
The final word on whether a user is held back. Every gate (login, ordering, comments, wp-admin) and every notice asks this.
apply_filters( 'wpcev_is_blocked', bool $blocked, int $user_id )
Parameters
$blocked | true when the plugin would hold this user back (the account carries the "not confirmed" flag), false when it would let them through (confirmed, or registered before the plugin was activated). The filter is not called for users in an exempt role or for user ID 0: the plugin never holds those back, whatever a callback returns. |
|---|---|
$user_id | The user being checked. |
Use it when
Another system already knows the address is good, for example members imported from an old site or accounts created through single sign-on, and you want them never to be held back without marking each one by hand.
Example
add_filter( 'wpcev_is_blocked', function ( $blocked, $user_id ) {
// Members imported from the old shop proved their address there.
if ( get_user_meta( $user_id, 'imported_from_legacy_shop', true ) ) {
return false;
}
return $blocked;
}, 10, 2 );
Good to know
- It runs on every check, several times per page. Keep the callback cheap: read a user meta or a role, do not query an API.
- Returning
truefor a user the plugin would let through, for example a confirmed user or one who registered before activation, does hold them back. Be sure that is what you want. Users in an exempt role are decided before the filter runs, so a callback cannot hold them back; remove the role from the exempt roles in the settings instead. - It changes the answer, not the stored status: the Users list still shows the user as pending. To change the status, see calling the plugin from your code.
wpcev_is_verified filter
Ask the plugin from your own code whether a user is confirmed.
$confirmed = apply_filters( 'wpcev_is_verified', false, int $user_id );
Parameters
false | Pass false. The plugin replaces the value with its answer; if the plugin is not active, your code gets false back and treats the user as not confirmed. |
|---|---|
$user_id | The user to ask about. |
Use it when
Your own code (a form plugin, a members-only download, a custom checkout) should refuse unconfirmed users too, and you want the same answer the plugin gives, including exempt roles, pre-existing users and anything a wpcev_is_blocked callback decided.
Example
add_filter( 'my_downloads_allowed', function ( $allowed, $user_id ) {
if ( ! $user_id || ! apply_filters( 'wpcev_is_verified', false, $user_id ) ) {
return false; // not logged in, or not confirmed yet
}
return $allowed;
}, 10, 2 );
Good to know
- This is a query, not a setting: adding your own callback to it would change the answer the plugin gives back to everyone else. Use
wpcev_is_blockedfor that. - "Confirmed" here means "not held back": users who registered before activation and exempt roles also answer
true. - The answer is about accounts only. For user ID
0(a visitor who is not logged in) it istrue, because the plugin holds back no one who is not an account. If guests must be refused too, check$user_id > 0yourself first, as the example does.
wpcev_skip_verification_on_register filter
Do not ask a new account to confirm. It is marked confirmed at once and no email is sent.
apply_filters( 'wpcev_skip_verification_on_register', bool $skip, int $user_id )
Parameters
$skip | Default false. Return true to skip. |
|---|---|
$user_id | The account that was just created. |
Use it when
The account was created in a way that already proved the address: a single sign-on plugin, an import, or an administrator creating the account in wp-admin.
Example
add_filter( 'wpcev_skip_verification_on_register', function ( $skip, $user_id ) {
// Accounts an administrator creates in wp-admin need no confirmation.
if ( is_admin() && current_user_can( 'create_users' ) ) {
return true;
}
return $skip;
}, 10, 2 );
Good to know
- The user is marked confirmed with the reason
filter. Because nothing proved the inbox, this is not passed on to WooCommerce 11's own confirmation record and does not link earlier guest orders. - It runs once, during registration. It has no effect on existing accounts.
wpcev_verify_on_password_reset filter
Whether finishing a password reset confirms an unconfirmed account. Default: yes, because the reset email reached the inbox.
apply_filters( 'wpcev_verify_on_password_reset', bool $verify, int $user_id )
Parameters
$verify | Default true. |
|---|---|
$user_id | The account whose password was reset. |
Example
// A password reset should not count as email confirmation on this site.
add_filter( 'wpcev_verify_on_password_reset', '__return_false' );
Good to know
- Covers both WordPress's own reset and WooCommerce's lost-password form.
- Users who registered before activation are never touched by this.
The verification email
The subject, body and sender are settings. These hooks cover what the settings cannot: a lifetime per user, a different link, extra headers, and knowing when a mail went out or failed.
wpcev_expiry_days filter since 1.0.8
How many days a verification link stays valid for one user. The setting is the default for everyone.
apply_filters( 'wpcev_expiry_days', int $days, int $user_id )
Parameters
$days | The setting (7 by default). |
|---|---|
$user_id | The user the link is for. |
Use it when
One group needs a different window: a live cohort that must confirm within a day, or invited business customers who get a month.
Example
add_filter( 'wpcev_expiry_days', function ( $days, $user_id ) {
$user = get_userdata( $user_id );
if ( $user && in_array( 'wholesale_customer', (array) $user->roles, true ) ) {
return 30;
}
return $days;
}, 10, 2 );
Good to know
- The result is clamped to 1 to 90 days, the same range as the setting. A link can never be made permanent.
- The filter runs when the email is written (the
%expiry%and%expiry_date%placeholders) and again when the link is clicked. Decide from something that does not change in between, such as the role at registration or a meta you set yourself, or the email and the check disagree. - The WooCommerce email preview in wp-admin has no real user and shows the setting.
wpcev_verification_url filter
The link placed in the email.
apply_filters( 'wpcev_verification_url', string $url, int $user_id, string $token )
Parameters
$url | The home URL with wpcev_verify=<token> and uid=<id>. |
|---|---|
$user_id | The recipient. |
$token | The plaintext token. Never log or store it. |
Example
add_filter( 'wpcev_verification_url', function ( $url, $user_id, $token ) {
// Tag clicks from the verification mail in analytics.
return add_query_arg( 'utm_source', 'verification-email', $url );
}, 10, 3 );
Good to know
- Keep the
wpcev_verifyanduidparameters and keep the link on this site. The plugin handles it on any page of the site, so a different path is fine; a different host is not. - The visitor is shown a "Confirm my email" button first unless they are logged in as that account. That protects against mail scanners and is not something a filter should work around.
wpcev_verification_email filter
Subject, body, headers and recipient of the plain-text email, after the placeholders were filled in.
apply_filters( 'wpcev_verification_email', array $args, string $token )
Parameters
$args | An array with subject, body, headers (array of strings), to and user_id. |
|---|---|
$token | The plaintext token, in case you build your own link. Never log or store it. |
Example
add_filter( 'wpcev_verification_email', function ( $args, $token ) {
$args['headers'][] = 'Reply-To: Student services <help@example.com>';
$args['body'] .= "\n\nQuestions? Reply to this email and we will help.";
return $args;
}, 10, 2 );
Good to know
- Only for the plain-text format. When the email format setting is WooCommerce's template, the mail is a WooCommerce email with the id
wpcev_verification: edit it under WooCommerce > Settings > Emails, or use WooCommerce's own filters such aswoocommerce_email_subject_wpcev_verification. - For the text alone the settings page is enough: subject and body are editable there, with placeholders.
wpcev_verification_sent action since 1.0.8
A verification email was handed to wp_mail() and accepted.
do_action( 'wpcev_verification_sent', int $user_id )
Parameters
$user_id | The recipient. The address is get_userdata( $user_id )->user_email. |
|---|
Use it when
You keep an activity log, a CRM timeline or a funnel (registered, mail sent, confirmed) and want the "sent" step without wrapping wp_mail.
Example
add_action( 'wpcev_verification_sent', function ( $user_id ) {
my_crm()->timeline( $user_id, 'Verification email sent' );
} );
Good to know
- Fires on every path: the first mail at registration, a resend from a notice or the login page, a changed address, an admin's Resend button and WP-CLI.
- "Accepted by wp_mail()" is not "delivered". Delivery is the mail server's business.
- The token and the link are deliberately not passed.
wpcev_verification_send_failed action since 1.0.8
A verification email could not be sent: wp_mail() returned false.
do_action( 'wpcev_verification_send_failed', int $user_id, string $code )
Parameters
$user_id | The customer who did not get the mail. |
|---|---|
$code | wp_mail_failed. |
Use it when
You want to know the moment the site's mail stops working, in a channel that does not depend on that mail.
Example
add_action( 'wpcev_verification_send_failed', function ( $user_id, $code ) {
wp_remote_post( 'https://alerts.example.com/hooks/mail', array(
'timeout' => 3,
'body' => array( 'site' => home_url(), 'user' => $user_id, 'code' => $code ),
) );
}, 10, 2 );
Good to know
- The plugin also writes the failure to the "Failed sends" tab and Site Health reports recent failures. This action is for your own alerting.
- The customer's previous link, if there was one, stays valid: a failed resend never destroys a working link.
What customers see
Wording and placement of what an unconfirmed customer reads, and where a confirmed one lands. For a different language, translate the plugin instead; these hooks are for a different message, or no message, on your site.
wpcev_notice_message filter since 1.0.8
The text of the main notices an unconfirmed customer reads, with a context that says where it is shown.
apply_filters( 'wpcev_notice_message', string $html, string $context, int $user_id )
Parameters
$html | The message, already escaped. In account, order and registration it contains <strong> (the address). account and order also carry the resend link (<a class="wpcev-resend"> with its countdown attribute), and order the "Change it" link. login and the two banners are plain sentences. |
|---|---|
$context | account (the My Account notice), order (cart, classic checkout, the Cart and Checkout blocks, and the Pay for order page, whose text has no links), registration (the one-time notice after signing up), login (the login error), frontend_banner (the banner on sites without WooCommerce) or admin_banner (the wp-admin banner). |
$user_id | The customer. 0 for login, where the user is not known yet. |
Use it when
The wording does not fit your site: a school talks to students, not customers; a members' club wants a different tone; you want to add a sentence about the spam folder.
Example
add_filter( 'wpcev_notice_message', function ( $html, $context, $user_id ) {
if ( 'login' === $context ) {
return 'Your student account is waiting for email confirmation. Open the link we sent you, then log in.';
}
if ( 'account' === $context ) {
return $html . ' <strong>Tip:</strong> check your spam folder too.';
}
return $html;
}, 10, 3 );
Good to know
- Only
<a href class data-wpcev-available-at>and<strong>survive; everything else is stripped. An empty return keeps the original. - If you replace a message that contained the resend link, the customer loses the way to ask for a new email from that place. Keep the link: it is the
<a class="wpcev-resend" ...>in$html. - For
loginthe value must be identical on every call (no user, no time, no randomness): the plugin calls the filter again to find its own login error by this text and add the resend link on WooCommerce login forms. Keepregistrationstable for one user too; the plugin recognises that notice in the queue the same way. - Short one-off messages are not passed through this filter: the result after a link is opened, the resend results, the comment refusal and the disabled Place order note. Reword those with a translation file (for example with Loco Translate), text domain
wpcoretools-email-verify. - For
frontend_bannerandadmin_banneryou get the sentence only; the plugin adds the resend link after it.
wpcev_show_notice filter since 1.0.8
Hide the notice for an unconfirmed customer on some pages. Display only: the gates still apply.
apply_filters( 'wpcev_show_notice', bool $show, string $location, int $user_id )
Parameters
$show | Default true. |
|---|---|
$location | account (My Account), cart and checkout (the classic cart and checkout notice), frontend (the banner on every front-end page of a site without WooCommerce) or admin (the wp-admin banner). |
$user_id | The customer. |
Use it when
On a site without WooCommerce the banner is printed on every front-end page, including a course player or a landing page where it is in the way.
Example
add_filter( 'wpcev_show_notice', function ( $show, $location, $user_id ) {
// Only on the student dashboard, nowhere else on the front end.
if ( 'frontend' === $location && ! is_page( 'dashboard' ) ) {
return false;
}
return $show;
}, 10, 3 );
Good to know
- Hiding a notice also hides its resend link. The refusal messages on checkout and in the Store API keep theirs, and the login page offers the resend form while the setting "Allow logged-out resend" is on (it is by default).
- The My Account notice is skipped once on the page a customer lands on right after registering, whatever the filter says: the sign-up notice already told them.
- It does not touch the gates. A customer who sees no notice is still refused when they try to order.
wpcev_verify_redirect_url filter since 1.0.8
Where a visitor lands after the verification link worked. The setting "After confirming, send the customer to" covers the common case; this filter decides per request.
apply_filters( 'wpcev_verify_redirect_url', string $url, int $user_id, string $result, string $viewer )
Parameters
$url | The page from the setting, or '' for the built-in result (My Account with a notice when WooCommerce is active, otherwise the plugin's own confirmation page). Return '' to keep that. |
|---|---|
$user_id | The account that was confirmed, when the request proves it: a link used for the first time, or the owner is logged in. 0 for a repeated click from a browser that is not logged in as that account. |
$result | ok (confirmed just now) or already (a second click, or a mail scanner opening a link that already worked). |
$viewer | guest (not logged in, the usual case), self (logged in as that account) or other (logged in as a different account). |
Use it when
A customer who is already logged in should go straight to the content, while a logged-out one needs a page with a login link. Or different groups have different landing pages.
Example
add_filter( 'wpcev_verify_redirect_url', function ( $url, $user_id, $result, $viewer ) {
if ( 'self' === $viewer ) {
return home_url( '/my-courses/' ); // logged in: straight to the content
}
return home_url( '/email-verification-success/' ); // a page with a login link
}, 10, 4 );
Good to know
- The URL must be on this site; relative paths and same-host URLs are accepted. An address on another host is ignored and the built-in result is shown, rather than WordPress's usual fallback to wp-admin (the
allowed_redirect_hostsfilter widens the check). - Clicking the link does not log anyone in. A page for
guestvisitors should offer a login link. - Expired and invalid links never come here: they keep the built-in pages, which carry the resend link.
- Runs after the account was marked confirmed and after earlier guest orders were linked, so your callback may read the new status.
wpcev_verify_landing filter since 1.0.8
Title and body of the plugin's own result page, on sites without WooCommerce. With WooCommerce the result is a My Account notice instead.
apply_filters( 'wpcev_verify_landing', array $landing, string $result )
Parameters
$landing | array( 'title' => string, 'body' => string ). The title is plain text; the body is HTML and goes through wp_kses_post(). |
|---|---|
$result | ok, already, expired, expired_resent (the link had expired and a fresh one was just mailed) or invalid. |
Use it when
You use the built-in page (no success URL set) but want your own words, or your own links on the expired and invalid pages, which the success URL deliberately leaves alone.
Example
add_filter( 'wpcev_verify_landing', function ( $landing, $result ) {
if ( 'ok' === $result ) {
$landing['title'] = 'Welcome aboard';
$landing['body'] = '<p>Your email is confirmed.</p>'
. '<p><a class="button" href="' . esc_url( home_url( '/login/' ) ) . '">Log in</a></p>';
}
return $landing;
}, 10, 2 );
Good to know
- The built-in "Go to login" buttons use
wp_login_url(). A custom login page set through WordPress'slogin_urlfilter is already honoured without this hook. - The HTTP status stays 200 for a confirmed address and 410 otherwise; a missing or non-string title or body keeps the default.
Events to listen for
Actions that tell your code what happened. Pick by what you need to know: that the inbox was proven, that the status changed for any reason, or that a link failed.
wpcev_email_confirmed action
The customer proved they control the inbox.
do_action( 'wpcev_email_confirmed', int $user_id, string $source )
Parameters
$user_id | The confirmed account. |
|---|---|
$source | link (the verification link), password_reset (a completed reset), woocommerce (WooCommerce 11's own confirmation) or multisite (WordPress's multisite activation key). |
Use it when
Something should happen only once the address is really proven: subscribe the customer to the newsletter they ticked, hand them a welcome coupon, start an onboarding sequence. The plugin itself uses this moment to link earlier guest orders to the account.
Example
add_action( 'wpcev_email_confirmed', function ( $user_id, $source ) {
if ( get_user_meta( $user_id, 'newsletter_opt_in', true ) ) {
my_newsletter_subscribe( get_userdata( $user_id )->user_email );
}
}, 10, 2 );
Good to know
- It does not fire when an admin marks a user verified, for exempt roles or for
wpcev_skip_verification_on_register: nothing was proven there. For every status change, usewpcev_user_verified. - To redirect the visitor after the link, use
wpcev_verify_redirect_urlrather than redirecting from here: this action also fires during a password reset.
wpcev_user_verified action
The account was marked confirmed, for any reason.
do_action( 'wpcev_user_verified', int $user_id, string $reason )
Parameters
$user_id | The account. |
|---|---|
$reason | link, password_reset, multisite, woocommerce (proof of the inbox; woocommerce also covers customers the Tools-tab sync takes over from WooCommerce's own record), admin (a Mark verified action, the profile, WP-CLI), exempt (an exempt role at registration), filter (wpcev_skip_verification_on_register), or '' from code that gave no reason. |
Example
add_action( 'wpcev_user_verified', function ( $user_id, $reason ) {
update_user_meta( $user_id, 'crm_email_status', 'verified:' . $reason );
}, 10, 2 );
wpcev_user_unverified action
The account was marked not confirmed.
do_action( 'wpcev_user_unverified', int $user_id, string $reason )
Parameters
$user_id | The account. |
|---|---|
$reason | admin (a Mark unverified action, the profile, WP-CLI), email_change (the address was changed and must be confirmed again), register (a new account), grandfathered (the Tools-tab action for users from before the plugin), or '' from code that gave no reason. |
Example
add_action( 'wpcev_user_unverified', function ( $user_id, $reason ) {
if ( 'email_change' === $reason ) {
my_crm()->timeline( $user_id, 'Changed email address, confirmation pending' );
}
}, 10, 2 );
wpcev_verify_link_failed action since 1.0.8
A verification link was used but did not work.
do_action( 'wpcev_verify_link_failed', int $user_id, string $problem )
Parameters
$user_id | The account, for expired and expired_resent (the link matched, it was only too old). 0 for invalid: the id in the request proved nothing. |
|---|---|
$problem | expired, expired_resent (the plugin just mailed a fresh link, because "Auto-resend on expired link" is on) or invalid. |
Use it when
Support should know that a student clicked a stale link, or your funnel has an "expired" step.
Example
add_action( 'wpcev_verify_link_failed', function ( $user_id, $problem ) {
if ( $user_id && 'expired' === $problem ) {
my_crm()->timeline( $user_id, 'Clicked an expired verification link' );
}
}, 10, 2 );
Good to know
- Do not alert, mail or write per user when
$user_idis0. Anyone can request the URL with any id and a made-up token; acting on it would turn your listener into a harassment tool. - Successful clicks are reported by
wpcev_email_confirmed.
Changing the address
An unconfirmed customer can correct a mistyped address from the notice on My Account ("Wrong address? Change it"). These hooks apply to that form.
wpcev_new_email_errors filter
Refuse a new address given in the "Wrong address?" form.
apply_filters( 'wpcev_new_email_errors', WP_Error $errors, string $email, int $user_id )
Parameters
$errors | Errors found so far. Add one to refuse; the message is shown to the customer. |
|---|---|
$email | The new address, already checked for format, duplicates and (if installed) Disposable Email Guard. |
$user_id | The account. |
Example
add_filter( 'wpcev_new_email_errors', function ( $errors, $email, $user_id ) {
if ( ! preg_match( '/@(students\.example\.edu|example\.edu)$/i', $email ) ) {
$errors->add( 'school_domain', 'Please use your school email address.' );
}
return $errors;
}, 10, 3 );
Good to know
- This covers only the plugin's own form. Registration and the Account details page are validated by WordPress and WooCommerce; use their hooks for those.
wpcev_run_wc_account_email_checks filter
Whether the "Wrong address?" form also runs other plugins' WooCommerce account-details validation on the new address.
apply_filters( 'wpcev_run_wc_account_email_checks', bool $run )
Example
// Another plugin's account validation misfires on this form: skip it here.
add_filter( 'wpcev_run_wc_account_email_checks', '__return_false' );
Good to know
- Default
true: the form fires WooCommerce'swoocommerce_save_account_details_errorswith the new address so plugins that restrict domains or check for duplicates keep working. Only relevant with WooCommerce.
WooCommerce
WooCommerce 11 keeps its own "Email confirmation" record per customer. The plugin keeps the two in step; one filter controls that, and another names custom reasons on the profile.
wpcev_sync_to_woocommerce filter
Whether a status change is passed on to WooCommerce 11's own confirmation record.
apply_filters( 'wpcev_sync_to_woocommerce', bool $sync, int $user_id, string $reason, string $direction )
Parameters
$sync | Default true. |
|---|---|
$user_id | The customer. |
$reason | link, password_reset, multisite, admin or backfill. Only reasons that prove the inbox or are an admin decision are ever synced. |
$direction | verify or unverify. |
Example
// Keep WooCommerce's record as it is when an admin unticks a customer here.
add_filter( 'wpcev_sync_to_woocommerce', function ( $sync, $user_id, $reason, $direction ) {
if ( 'unverify' === $direction && 'admin' === $reason ) {
return false;
}
return $sync;
}, 10, 4 );
Good to know
- Does nothing on WooCommerce before 11 or without WooCommerce.
- When WooCommerce confirms a customer through its own link, the plugin follows; that direction has no filter, WooCommerce is the authority on its own record.
wpcev_verified_via_label filter
The "how was this address verified" label on the user profile, for reasons the plugin does not know.
apply_filters( 'wpcev_verified_via_label', string $label, string $via, int $user_id )
Parameters
$label | The label the plugin would show. |
|---|---|
$via | The stored reason, for example link, admin, or the reason your own code passed to mark_verified(). |
$user_id | The user whose profile is shown. |
Example
add_filter( 'wpcev_verified_via_label', function ( $label, $via, $user_id ) {
return 'campus_sso' === $via ? 'Campus single sign-on' : $label;
}, 10, 3 );
Auto-delete of abandoned sign-ups
Off by default. When it is on, a daily job deletes accounts that never confirmed after the chosen number of days, skipping exempt roles, anyone with WooCommerce orders and anyone with content. Three hooks let you keep an account, redirect its content, or record the deletion.
wpcev_should_purge_user filter
Keep an account the auto-delete would remove.
apply_filters( 'wpcev_should_purge_user', bool $delete, int $user_id )
Example
add_filter( 'wpcev_should_purge_user', function ( $delete, $user_id ) {
// Students with an enrolment are kept, confirmed or not.
if ( get_user_meta( $user_id, 'enrolment_id', true ) ) {
return false;
}
return $delete;
}, 10, 2 );
wpcev_purge_reassign_to filter
The user that receives any remaining content of a deleted account. Default null: WordPress's own behaviour.
apply_filters( 'wpcev_purge_reassign_to', int|null $reassign, int $user_id )
Example
add_filter( 'wpcev_purge_reassign_to', function ( $reassign, $user_id ) {
return 1; // the site owner's account
}, 10, 2 );
Good to know
- Accounts with any posts, pages or media are skipped by the auto-delete anyway, so this rarely matters. It exists so that nothing is ever lost if it does.
wpcev_before_purge_user action since 1.0.8
The auto-delete is about to remove an account. The user still exists at this point.
do_action( 'wpcev_before_purge_user', int $user_id, int|null $reassign )
Parameters
$user_id | The account about to be deleted. get_userdata() still works here. |
|---|---|
$reassign | Who receives remaining content, or null. |
Use it when
You keep a deletion record for data-protection purposes, or another system (a newsletter tool, a CRM) must forget the person too.
Example
add_action( 'wpcev_before_purge_user', function ( $user_id, $reassign ) {
$user = get_userdata( $user_id );
if ( $user ) {
my_newsletter_unsubscribe( $user->user_email );
my_deletion_log( 'unconfirmed account removed', $user->user_email );
}
}, 10, 2 );
Good to know
- This is a notification. To keep the account, use
wpcev_should_purge_user, which runs first. - Only the plugin's auto-delete fires it. An admin deleting a user from the Users list goes through WordPress's own
delete_useraction.
Calling the plugin from your code
Hooks cover almost everything, but sometimes your code needs to act: confirm an account because your own system verified the address, or send a fresh link. The plugin's objects are reachable through wpcev(). Check that the function exists first, so your code survives the plugin being deactivated.
if ( function_exists( 'wpcev' ) ) {
// Mark a user confirmed, naming your reason (shown on the profile; see wpcev_verified_via_label).
wpcev()->tokens->mark_verified( $user_id, 'campus_sso' );
// Ask for the stored status: 'verified', 'unverified', 'grandfathered' or 'exempt' ('invalid' for ID 0).
$status = wpcev()->tokens->status( $user_id );
// Send a fresh verification email, honouring the resend wait.
// Returns 'sent', 'throttled', 'locked', 'failed' or 'invalid'.
$result = wpcev()->mailer->send_verification( $user_id, true );
}
mark_verified()fireswpcev_user_verifiedwith your reason. A reason of your own is not passed on to WooCommerce 11's record (only proofs of the inbox and admin decisions are), and does not link guest orders; callwc_update_new_customer_past_orders()yourself if that is what you want.- To take confirmation away,
wpcev()->tokens->unmark_verified( $user_id, 'my_reason' ). It does not send a new link; callsend_verification()for that. - From the command line the same is available as
wp wpcev status|verify|unverify|resend <user>.
Missing a hook? Tell us what you are trying to do on the WordPress.org support forum (opens in a new tab) or through the contact page. Hooks are added when there is a real site that needs one; most of the ones above started as a support question.
Back to the plugin
Everything on this page is optional. The plugin page explains what Email Verify does for a site owner, no code involved.
WPCoreTools Email Verify