{"id":370020,"date":"2026-09-19T15:19:49","date_gmt":"2026-09-19T15:19:49","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/pro-admin\/"},"modified":"2026-10-07T08:26:47","modified_gmt":"2026-10-07T08:26:47","slug":"adminkeep","status":"publish","type":"plugin","link":"https:\/\/de.wordpress.org\/plugins\/adminkeep\/","author":4091607,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"2.6.0","stable_tag":"2.6.0","tested":"7.1.3","requires":"6.9","requires_php":"7.4","requires_plugins":null,"header_name":"Adminkeep","header_author":"Adminkeep","header_description":"Turn off comments, block new plugin installs, and duplicate posts safely. Every lock is instantly reversible. No ads, no nags, no notices.","assets_banners_color":"1a1a2e","last_updated":"2026-10-07 08:26:47","external_support_url":"","external_repository_url":"","donate_link":"","header_plugin_uri":"https:\/\/adminkeep.com","header_author_uri":"https:\/\/adminkeep.com","rating":0,"author_block_rating":0,"active_installs":70,"downloads":1379,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.1.0":{"tag":"1.1.0","author":"sajib1223","date":"2026-09-19 15:19:14","revision":3703401},"1.10.0":{"tag":"1.10.0","author":"sajib1223","date":"2026-09-25 10:11:37","revision":3712819},"1.2.0":{"tag":"1.2.0","author":"sajib1223","date":"2026-09-20 00:51:02","revision":3703754},"1.3.0":{"tag":"1.3.0","author":"sajib1223","date":"2026-09-20 10:55:39","revision":3704149},"1.4.0":{"tag":"1.4.0","author":"sajib1223","date":"2026-09-20 17:31:48","revision":3704509},"1.5.0":{"tag":"1.5.0","author":"sajib1223","date":"2026-09-21 03:13:55","revision":3704788},"1.6.0":{"tag":"1.6.0","author":"sajib1223","date":"2026-09-21 05:08:23","revision":3704870},"1.7.0":{"tag":"1.7.0","author":"sajib1223","date":"2026-09-21 17:29:44","revision":3706030},"1.8.0":{"tag":"1.8.0","author":"sajib1223","date":"2026-09-22 11:25:06","revision":3707168},"1.8.1":{"tag":"1.8.1","author":"sajib1223","date":"2026-09-24 04:10:04","revision":3710457},"1.9.0":{"tag":"1.9.0","author":"sajib1223","date":"2026-09-24 04:35:16","revision":3710472},"2.0.0":{"tag":"2.0.0","author":"sajib1223","date":"2026-09-26 14:52:20","revision":3714357},"2.1.0":{"tag":"2.1.0","author":"sajib1223","date":"2026-09-27 21:21:46","revision":3716066},"2.2.0":{"tag":"2.2.0","author":"sajib1223","date":"2026-09-28 02:21:17","revision":3716200},"2.3.0":{"tag":"2.3.0","author":"sajib1223","date":"2026-09-30 09:35:09","revision":3720819},"2.4.0":{"tag":"2.4.0","author":"sajib1223","date":"2026-09-30 17:55:26","revision":3721786},"2.5.0":{"tag":"2.5.0","author":"sajib1223","date":"2026-10-05 08:26:23","revision":3728397},"2.6.0":{"tag":"2.6.0","author":"sajib1223","date":"2026-10-07 08:26:47","revision":3732128}},"upgrade_notice":[],"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3703401,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3703401,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256},"icon.svg":{"filename":"icon.svg","revision":3703401,"resolution":false,"location":"assets","locale":false}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3703401,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3703401,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{"blueprint.json":{"filename":"blueprint.json","revision":3732129,"resolution":false,"location":"assets","locale":"","contents":"{\"$schema\":\"https:\\\/\\\/playground.wordpress.net\\\/blueprint-schema.json\",\"meta\":{\"title\":\"Adminkeep preview\",\"description\":\"Installs Adminkeep from wordpress.org, switches on a few features that show well, sends some sample emails through wp_mail() and opens the Email Log.\",\"author\":\"shazzad\"},\"landingPage\":\"\\\/wp-admin\\\/admin.php?page=adminkeep-email-log\",\"preferredVersions\":{\"php\":\"8.3\",\"wp\":\"latest\"},\"steps\":[{\"step\":\"login\",\"username\":\"admin\"},{\"step\":\"installPlugin\",\"pluginData\":{\"resource\":\"wordpress.org\\\/plugins\",\"slug\":\"adminkeep\"},\"options\":{\"activate\":true}},{\"step\":\"runPHP\",\"code\":\"<?php\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\n\\n\\\/\\\/ The same writers the settings screen, the REST route and `wp adminkeep` use, so the preview\\n\\\/\\\/ stores exactly what a real site would.\\n$registry = \\\\Adminkeep\\\\Plugin::instance()->registry();\\n$writer   = new \\\\Adminkeep\\\\Service\\\\SettingsWriter( $registry );\\n\\nforeach ( array( 'disable_comments', 'registration_lock', 'username_privacy', 'custom_css', 'header_footer_code', 'duplicate', 'email_log', 'nice_emails' ) as $feature_id ) {\\n\\t$feature = $registry->get( $feature_id );\\n\\n\\tif ( $feature ) {\\n\\t\\t$writer->set_enabled( $feature, true );\\n\\t}\\n}\\n\\n\\\\Adminkeep\\\\Feature\\\\CustomCss::save(\\n\\t\\\"\\\/* Saved with Adminkeep. Edit it under Appearance > Custom CSS. *\\\/\\\\n\\\" .\\n\\t\\\"body::before {\\\\n\\\" .\\n\\t\\\"\\\\tcontent: \\\\\\\"This bar comes from Adminkeep's Custom CSS\\\\\\\";\\\\n\\\" .\\n\\t\\\"\\\\tdisplay: block;\\\\n\\\" .\\n\\t\\\"\\\\tpadding: 8px 16px;\\\\n\\\" .\\n\\t\\\"\\\\tbackground: #1e1e1e;\\\\n\\\" .\\n\\t\\\"\\\\tcolor: #fff;\\\\n\\\" .\\n\\t\\\"\\\\tfont: 14px\\\/1.4 system-ui, sans-serif;\\\\n\\\" .\\n\\t\\\"\\\\ttext-align: center;\\\\n\\\" .\\n\\t\\\"}\\\\n\\\"\\n);\\n\\n\\\\Adminkeep\\\\Feature\\\\HeaderFooterCode::save(\\n\\tarray(\\n\\t\\t'head'   => '<!-- Adminkeep preview: this comment was added under Appearance > Header & Footer Code (page head). -->',\\n\\t\\t'footer' => '<!-- Adminkeep preview: this comment was added under Appearance > Header & Footer Code (footer). -->',\\n\\t),\\n\\t1\\n);\\n\"},{\"step\":\"runPHP\",\"code\":\"<?php\\n\\\/\\\/ A request of its own: Email Log and Nice Default Emails were switched on by the step before, so\\n\\\/\\\/ this load boots them the normal way and every email below goes through their real hooks.\\nrequire_once '\\\/wordpress\\\/wp-load.php';\\nrequire_once ABSPATH . WPINC . '\\\/PHPMailer\\\/PHPMailer.php';\\nrequire_once ABSPATH . WPINC . '\\\/PHPMailer\\\/SMTP.php';\\nrequire_once ABSPATH . WPINC . '\\\/PHPMailer\\\/Exception.php';\\n\\n\\\/\\\/ Playground cannot deliver mail. wp_mail() reuses $phpmailer when it already holds a PHPMailer,\\n\\\/\\\/ so this one builds each message as usual and reports it accepted without sending anything;\\n\\\/\\\/ wp_mail_succeeded then fires and the log marks the row Sent.\\nclass Adminkeep_Preview_Mailer extends \\\\PHPMailer\\\\PHPMailer\\\\PHPMailer {\\n\\tpublic function postSend() {\\n\\t\\treturn true;\\n\\t}\\n}\\n\\n$GLOBALS['phpmailer'] = new Adminkeep_Preview_Mailer( true );\\n\\n\\\/\\\/ WordPress sends its own email from wordpress@ plus the site's host, and a Playground host such\\n\\\/\\\/ as 127.0.0.1 is not an address PHPMailer accepts. Only that default is replaced; an email that\\n\\\/\\\/ names its own sender keeps it.\\nadd_filter(\\n\\t'wp_mail_from',\\n\\tstatic function ( $from ) {\\n\\t\\treturn 0 === strpos( $from, 'wordpress@' ) ? 'wordpress@example.com' : $from;\\n\\t}\\n);\\n\\n\\\/\\\/ Example addresses throughout, and the documentation IP core quotes in the reset email, since a\\n\\\/\\\/ blueprint step has no visitor to take one from.\\nupdate_option( 'admin_email', 'admin@example.com' );\\n\\nif ( empty( $_SERVER['REMOTE_ADDR'] ) ) {\\n\\t$_SERVER['REMOTE_ADDR'] = '203.0.113.24';\\n}\\n\\n\\\/\\\/ Core account emails, which Nice Default Emails dresses in the HTML layout. The reset link in\\n\\\/\\\/ the second one is taken out by Email Log before it is stored.\\n$demo_user = username_exists( 'demo' );\\n\\nif ( ! $demo_user ) {\\n\\t$demo_user = wp_insert_user(\\n\\t\\tarray(\\n\\t\\t\\t'user_login' => 'demo',\\n\\t\\t\\t'user_email' => 'demo@example.org',\\n\\t\\t\\t'user_pass'  => wp_generate_password( 24 ),\\n\\t\\t\\t'role'       => 'subscriber',\\n\\t\\t)\\n\\t);\\n}\\n\\nif ( ! is_wp_error( $demo_user ) ) {\\n\\twp_new_user_notification( $demo_user, null, 'admin' );\\n\\tretrieve_password( 'demo' );\\n}\\n\\n\\\/\\\/ A contact-form plugin's email: plain text from a plugin, so it is logged as it was sent.\\nwp_mail(\\n\\t'hello@example.com',\\n\\t'New message from your website',\\n\\t\\\"Name: Alex Example\\\\n\\\" .\\n\\t\\\"Email: alex@example.org\\\\n\\\\n\\\" .\\n\\t\\\"Message:\\\\n\\\" .\\n\\t\\\"Hi there, do you ship to Canada? I'd like to order two of the ceramic mugs.\\\\n\\\\n\\\" .\\n\\t\\\"--\\\\n\\\" .\\n\\t\\\"Sent from the contact form on your website.\\\",\\n\\tarray(\\n\\t\\t'From: Example Store <forms@example.com>',\\n\\t\\t'Reply-To: Alex Example <alex@example.org>',\\n\\t)\\n);\\n\\n\\\/\\\/ A shop's HTML order confirmation, logged with its markup and shown rendered in the preview.\\n$order_html = '<!DOCTYPE html><html><body style=\\\"margin:0;padding:24px;background:#f0f2f5;font-family:Helvetica,Arial,sans-serif;color:#1d2327;\\\">'\\n\\t. '<table role=\\\"presentation\\\" width=\\\"100%\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"max-width:560px;margin:0 auto;background:#ffffff;border-radius:6px;overflow:hidden;\\\">'\\n\\t. '<tr><td style=\\\"background:#2271b1;padding:28px 32px;color:#ffffff;\\\">'\\n\\t. '<div style=\\\"font-size:13px;letter-spacing:.08em;text-transform:uppercase;opacity:.85;\\\">Example Store<\\\/div>'\\n\\t. '<h1 style=\\\"margin:6px 0 0;font-size:24px;font-weight:600;\\\">Thanks for your order<\\\/h1>'\\n\\t. '<\\\/td><\\\/tr>'\\n\\t. '<tr><td style=\\\"padding:28px 32px;\\\">'\\n\\t. '<p style=\\\"margin:0 0 16px;font-size:15px;line-height:1.5;\\\">Hi Sam, we have received order <strong>#1042<\\\/strong> and are getting it ready. We will email you again when it ships.<\\\/p>'\\n\\t. '<table role=\\\"presentation\\\" width=\\\"100%\\\" cellpadding=\\\"0\\\" cellspacing=\\\"0\\\" style=\\\"font-size:14px;border-collapse:collapse;\\\">'\\n\\t. '<tr><th align=\\\"left\\\" style=\\\"padding:8px 0;border-bottom:2px solid #dcdcde;\\\">Item<\\\/th><th align=\\\"center\\\" style=\\\"padding:8px 0;border-bottom:2px solid #dcdcde;\\\">Qty<\\\/th><th align=\\\"right\\\" style=\\\"padding:8px 0;border-bottom:2px solid #dcdcde;\\\">Price<\\\/th><\\\/tr>'\\n\\t. '<tr><td style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">Ceramic mug, sea green<\\\/td><td align=\\\"center\\\" style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">2<\\\/td><td align=\\\"right\\\" style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">$36.00<\\\/td><\\\/tr>'\\n\\t. '<tr><td style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">Linen tea towel<\\\/td><td align=\\\"center\\\" style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">1<\\\/td><td align=\\\"right\\\" style=\\\"padding:10px 0;border-bottom:1px solid #f0f0f1;\\\">$14.00<\\\/td><\\\/tr>'\\n\\t. '<tr><td colspan=\\\"2\\\" style=\\\"padding:10px 0;\\\">Shipping<\\\/td><td align=\\\"right\\\" style=\\\"padding:10px 0;\\\">$5.00<\\\/td><\\\/tr>'\\n\\t. '<tr><td colspan=\\\"2\\\" style=\\\"padding:12px 0;border-top:2px solid #dcdcde;font-weight:600;\\\">Total<\\\/td><td align=\\\"right\\\" style=\\\"padding:12px 0;border-top:2px solid #dcdcde;font-weight:600;font-size:16px;\\\">$55.00<\\\/td><\\\/tr>'\\n\\t. '<\\\/table>'\\n\\t. '<p style=\\\"margin:24px 0 0;\\\"><a href=\\\"https:\\\/\\\/shop.example.com\\\/account\\\/orders\\\/1042\\\/\\\" style=\\\"display:inline-block;background:#2271b1;color:#ffffff;text-decoration:none;padding:10px 18px;border-radius:4px;font-size:14px;\\\">View your order<\\\/a><\\\/p>'\\n\\t. '<\\\/td><\\\/tr>'\\n\\t. '<tr><td style=\\\"padding:18px 32px;background:#f6f7f7;font-size:12px;color:#646970;\\\">Example Store &middot; 1 Example Street, Springfield &middot; <a href=\\\"https:\\\/\\\/shop.example.com\\\/\\\" style=\\\"color:#646970;\\\">shop.example.com<\\\/a><\\\/td><\\\/tr>'\\n\\t. '<\\\/table><\\\/body><\\\/html>';\\n\\nwp_mail(\\n\\t'Sam Example <sam@example.org>',\\n\\t'Your Example Store order #1042',\\n\\t$order_html,\\n\\tarray(\\n\\t\\t'From: Example Store <orders@example.com>',\\n\\t\\t'Content-Type: text\\\/html; charset=UTF-8',\\n\\t)\\n);\\n\"}]}"}},"all_blocks":{"adminkeep\/contact-form":{"$schema":"https:\/\/schemas.wp.org\/trunk\/block.json","apiVersion":3,"name":"adminkeep\/contact-form","title":"Contact Form","category":"widgets","icon":"email","description":"A name, email and message form that emails you, protected by Cloudflare Turnstile or Google reCAPTCHA.","keywords":["contact","form","email"],"textdomain":"adminkeep","supports":{"html":false},"editorScript":"adminkeep-contact-form-block"}},"tagged_versions":["1.1.0","1.10.0","1.2.0","1.3.0","1.4.0","1.5.0","1.6.0","1.7.0","1.8.0","1.8.1","1.9.0","2.0.0","2.1.0","2.2.0","2.3.0","2.4.0","2.5.0","2.6.0"],"block_files":[],"assets_screenshots":{"screenshot-1.png":{"filename":"screenshot-1.png","revision":3732091,"resolution":"1","location":"assets","locale":"","width":1544,"height":1568},"screenshot-10.png":{"filename":"screenshot-10.png","revision":3716066,"resolution":"10","location":"assets","locale":"","width":1544,"height":931},"screenshot-11.png":{"filename":"screenshot-11.png","revision":3721786,"resolution":"11","location":"assets","locale":"","width":1544,"height":1248},"screenshot-12.png":{"filename":"screenshot-12.png","revision":3720819,"resolution":"12","location":"assets","locale":"","width":1544,"height":754},"screenshot-13.png":{"filename":"screenshot-13.png","revision":3720819,"resolution":"13","location":"assets","locale":"","width":1544,"height":778},"screenshot-14.png":{"filename":"screenshot-14.png","revision":3720819,"resolution":"14","location":"assets","locale":"","width":1544,"height":1457},"screenshot-15.png":{"filename":"screenshot-15.png","revision":3720819,"resolution":"15","location":"assets","locale":"","width":1544,"height":754},"screenshot-16.png":{"filename":"screenshot-16.png","revision":3720819,"resolution":"16","location":"assets","locale":"","width":1544,"height":629},"screenshot-17.png":{"filename":"screenshot-17.png","revision":3732091,"resolution":"17","location":"assets","locale":"","width":1544,"height":1280},"screenshot-18.png":{"filename":"screenshot-18.png","revision":3732091,"resolution":"18","location":"assets","locale":"","width":1544,"height":673},"screenshot-19.png":{"filename":"screenshot-19.png","revision":3732091,"resolution":"19","location":"assets","locale":"","width":1544,"height":1664},"screenshot-2.png":{"filename":"screenshot-2.png","revision":3703401,"resolution":"2","location":"assets","locale":"","width":1544,"height":1167},"screenshot-3.png":{"filename":"screenshot-3.png","revision":3716066,"resolution":"3","location":"assets","locale":"","width":1544,"height":1421},"screenshot-4.png":{"filename":"screenshot-4.png","revision":3716066,"resolution":"4","location":"assets","locale":"","width":1544,"height":1045},"screenshot-5.png":{"filename":"screenshot-5.png","revision":3716066,"resolution":"5","location":"assets","locale":"","width":1544,"height":1029},"screenshot-6.png":{"filename":"screenshot-6.png","revision":3716066,"resolution":"6","location":"assets","locale":"","width":1544,"height":879},"screenshot-7.png":{"filename":"screenshot-7.png","revision":3716066,"resolution":"7","location":"assets","locale":"","width":1544,"height":1351},"screenshot-8.png":{"filename":"screenshot-8.png","revision":3716066,"resolution":"8","location":"assets","locale":"","width":1544,"height":1158},"screenshot-9.png":{"filename":"screenshot-9.png","revision":3716066,"resolution":"9","location":"assets","locale":"","width":1544,"height":686}},"screenshots":{"1":"Five groups, nineteen features, one switch each. Turn on only what you need.","2":"Nothing is deleted until you have seen the exact count. Order notes and reviews are excluded unless you say otherwise.","3":"The administrator guard is on by default. Blocking plugin-created accounts is opt-in, because it breaks WooCommerce checkout.","4":"Stop plugin and theme installs and uploads, while updates keep working \u2014 and switch it back off from this same screen.","5":"Custom CSS lives under Appearance, in WordPress's own code editor, and stays when you switch themes.","6":"Edit CSS from the admin bar on any page of your site: the page restyles as you type, and nothing is saved until you press Save.","7":"Header &amp; Footer Code under Appearance: one box each for the head, the top of the body and the footer, and who last changed each one.","8":"SMTP under Settings: pick a provider, save, and send a test email that shows what the server said.","9":"Email Log in its own admin menu: every email your site sends, whether it went out, and filters for status, period and search.","10":"Open any logged email as it was sent, with its source a tab away. Scripts and remote images are blocked in the preview.","11":"Contact Form under Settings: where messages go, and the spam protection: a WordPress nonce out of the box, or Cloudflare Turnstile or Google reCAPTCHA. The shortcode and block are in the Usage box.","12":"Duplicate and Live Draft where you already work \u2014 the row actions, not a new menu.","13":"Rewrite a published page while it stays published. Merge back into the same post, same URL.","14":"The redirects WordPress core skips: hierarchical pages, and posts moved to a new parent.","15":"Sorting gets a screen of its own: drag a row where you want it \u2014 and the order applies to your front-end queries too.","16":"Swapping a file for a different format tells you what references it first, then keeps the old URL redirecting.","17":"Two-Factor Login on the login screen: after the password, a six-digit code emailed to the account's address, shown partly hidden, with the option to remember the device.","18":"Locked out? The recovery link emailed when you switch Two-Factor Login on opens this page, and one button turns the code step off without logging in.","19":"Two-Factor Login in the settings: choose which roles are asked for a code, and see where the recovery link was emailed."}},"plugin_section":[],"plugin_tags":[14833,26736,7825,17953,6459],"plugin_category":[],"plugin_contributors":[80023],"plugin_business_model":[],"class_list":["post-370020","plugin","type-plugin","status-publish","hentry","plugin_tags-disable-comments","plugin_tags-email-log","plugin_tags-enhancement","plugin_tags-enhancements","plugin_tags-lockdown","plugin_contributors-sajib1223","plugin_committers-sajib1223"],"banners":{"banner":"https:\/\/ps.w.org\/adminkeep\/assets\/banner-772x250.png?rev=3703401","banner_2x":"https:\/\/ps.w.org\/adminkeep\/assets\/banner-1544x500.png?rev=3703401","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":"https:\/\/ps.w.org\/adminkeep\/assets\/icon.svg?rev=3703401","icon":"https:\/\/ps.w.org\/adminkeep\/assets\/icon.svg?rev=3703401","icon_2x":false,"generated":false},"screenshots":[{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-1.png?rev=3732091","caption":"Five groups, nineteen features, one switch each. Turn on only what you need."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-2.png?rev=3703401","caption":"Nothing is deleted until you have seen the exact count. Order notes and reviews are excluded unless you say otherwise."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-3.png?rev=3716066","caption":"The administrator guard is on by default. Blocking plugin-created accounts is opt-in, because it breaks WooCommerce checkout."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-4.png?rev=3716066","caption":"Stop plugin and theme installs and uploads, while updates keep working \u2014 and switch it back off from this same screen."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-5.png?rev=3716066","caption":"Custom CSS lives under Appearance, in WordPress's own code editor, and stays when you switch themes."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-6.png?rev=3716066","caption":"Edit CSS from the admin bar on any page of your site: the page restyles as you type, and nothing is saved until you press Save."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-7.png?rev=3716066","caption":"Header &amp; Footer Code under Appearance: one box each for the head, the top of the body and the footer, and who last changed each one."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-8.png?rev=3716066","caption":"SMTP under Settings: pick a provider, save, and send a test email that shows what the server said."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-9.png?rev=3716066","caption":"Email Log in its own admin menu: every email your site sends, whether it went out, and filters for status, period and search."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-10.png?rev=3716066","caption":"Open any logged email as it was sent, with its source a tab away. Scripts and remote images are blocked in the preview."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-11.png?rev=3721786","caption":"Contact Form under Settings: where messages go, and the spam protection: a WordPress nonce out of the box, or Cloudflare Turnstile or Google reCAPTCHA. The shortcode and block are in the Usage box."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-12.png?rev=3720819","caption":"Duplicate and Live Draft where you already work \u2014 the row actions, not a new menu."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-13.png?rev=3720819","caption":"Rewrite a published page while it stays published. Merge back into the same post, same URL."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-14.png?rev=3720819","caption":"The redirects WordPress core skips: hierarchical pages, and posts moved to a new parent."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-15.png?rev=3720819","caption":"Sorting gets a screen of its own: drag a row where you want it \u2014 and the order applies to your front-end queries too."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-16.png?rev=3720819","caption":"Swapping a file for a different format tells you what references it first, then keeps the old URL redirecting."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-17.png?rev=3732091","caption":"Two-Factor Login on the login screen: after the password, a six-digit code emailed to the account's address, shown partly hidden, with the option to remember the device."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-18.png?rev=3732091","caption":"Locked out? The recovery link emailed when you switch Two-Factor Login on opens this page, and one button turns the code step off without logging in."},{"src":"https:\/\/ps.w.org\/adminkeep\/assets\/screenshot-19.png?rev=3732091","caption":"Two-Factor Login in the settings: choose which roles are asked for a code, and see where the recovery link was emailed."}],"raw_content":"<!--section=description-->\n<p>Site lockdown and admin enhancements for WordPress, under one idea: you decide what changes on this site.<\/p>\n\n<p><strong>Site Lock<\/strong> stops things changing behind your back \u2014 no new comment, no new plugin, no new user, no new account with admin rights. The rest are admin enhancements that make the changes you do want safe to make: an email log, custom CSS, header and footer code, SMTP, a contact form, duplicate and reorder posts, replace a file in place.<\/p>\n\n<p>Every feature is a single switch, off until you turn it on. <strong>Switching one off never leaves you repair work<\/strong>: the locks work through WordPress filters, so your site is exactly as it was (the devices Two-Factor Login remembers stay behind, doing nothing), and what you made with the Content features stays where you put it.<\/p>\n\n<h4>Site Lock<\/h4>\n\n<ul>\n<li><strong>Disable Comments<\/strong> \u2014 comments off everywhere, including direct POSTs from spam bots and the REST API. Nothing is written to your database, so switching it off brings every comment back. An optional cleanup button deletes spam and trashed comments, after showing you the exact count. <a href=\"https:\/\/adminkeep.com\/guides\/disable-comments-wordpress\/\">Guide<\/a><\/li>\n<li><strong>Registration Lockdown<\/strong> \u2014 stops new accounts being created, and refuses creation of or promotion to administrator. Blocked attempts are logged. <a href=\"https:\/\/adminkeep.com\/guides\/stop-spam-user-registration-wordpress\/\">Guide<\/a><\/li>\n<li><strong>Disable XML-RPC<\/strong> \u2014 closes <code>xmlrpc.php<\/code> completely, including pingbacks and <code>system.multicall<\/code>. <a href=\"https:\/\/adminkeep.com\/guides\/disable-xmlrpc-wordpress\/\">Guide<\/a><\/li>\n<li><strong>Disable File Editing<\/strong> \u2014 removes the built-in plugin and theme file editors, reversibly.<\/li>\n<li><strong>Installation Lockdown<\/strong> \u2014 no new plugins or themes, from WordPress.org or a ZIP, and no replacing one by uploading a ZIP, for anyone. Updates keep working, so security releases still reach your site. <a href=\"https:\/\/adminkeep.com\/guides\/block-plugin-installs-wordpress\/\">Guide<\/a><\/li>\n<li><strong>Username Privacy<\/strong> \u2014 keeps your usernames out of public view. Author pages, the <code>?author=1<\/code> probe, the REST users list, author sitemaps and embed previews stop naming your accounts to visitors; anyone logged in sees everything as before. Nothing is written, so switching it off reopens it all. <a href=\"https:\/\/adminkeep.com\/guides\/hide-wordpress-username\/\">Guide<\/a><\/li>\n<li><strong>Two-Factor Login<\/strong> \u2014 users in the roles you choose enter a six-digit code emailed to them after their password, so a stolen password alone no longer opens the account. The code screen emails the code when the user presses its button, so they can warn whoever reads that mailbox first, and the code works once, for up to ten minutes. Five wrong codes lock the code step for that account for 15 minutes, doubling on repeat. At most five code emails go to one user in ten minutes, and wrong codes are reported as failed logins, so login-limiting plugins count them. \"Remember this device\" skips the code on that browser for 30 days, or the number you set. On multisite, super admins are asked whenever administrators are. The code is asked for on the main login screen; other login forms, such as WooCommerce's My Account, send these users there. The REST API, application passwords and XML-RPC are not asked. Switching it on emails you a recovery link that turns Two-Factor Login off without logging in, in case you are ever locked out.<\/li>\n<\/ul>\n\n<h4>Appearance<\/h4>\n\n<ul>\n<li><strong>Custom CSS<\/strong> \u2014 CSS that belongs to your site instead of your theme. Edit it under Appearance with WordPress's own code editor, or open Edit CSS from the admin bar on any page and watch the page restyle as you type, the way the Customizer's CSS box used to. It stays when you switch themes, and your theme's Additional CSS is left alone.<\/li>\n<li><strong>Header &amp; Footer Code<\/strong> \u2014 a home for the snippets services ask you to paste into your site: analytics and verification tags in the head, a tag manager's fallback just after the body opens, chat widgets and scripts in the footer. Three boxes under Appearance with WordPress's code editor, printed on the front end exactly as you saved them, and kept when you change or update your theme. Each box shows who last changed it and when. Only administrators allowed to post unfiltered HTML can edit them.<\/li>\n<\/ul>\n\n<h4>Email<\/h4>\n\n<ul>\n<li><strong>SMTP<\/strong> \u2014 Send your site's email through an SMTP server so password resets and form messages arrive. Presets for Amazon SES, Brevo, Mailgun, SendGrid, Postmark, Zoho and Gmail; a test email that shows the server's own error; settings can live in wp-config.php. Moving from WP Mail SMTP? One click copies its SMTP connection settings. <a href=\"https:\/\/adminkeep.com\/guides\/wordpress-smtp-settings\/\">Guide<\/a><\/li>\n<li><strong>Email Log<\/strong> \u2014 Email Log, in its own item in the admin menu by default (or under Tools, if you prefer), lists the email your site sends, with recipient, subject and whether it was sent or failed, plus filters by status and date and a search. Open any email to see its sender and headers, and the email itself the way it looked when it went out, with remote images blocked. Content storage can be switched off to keep only the envelope. Password-reset and sign-in links are removed before an email is stored, and a Two-Factor Login code email keeps only its envelope. Works with or without the SMTP feature, and with other SMTP plugins too.<\/li>\n<li><strong>Nice Default Emails<\/strong> \u2014 WordPress's own plain-text emails (password resets, new-user and comment notices, update reports, personal data requests, and multisite sign-ups), and Adminkeep's own contact form, go out in one clean HTML layout headed by your site's name, with links you can click. WooCommerce and other plugins' emails, and anything already sent as HTML, are left exactly as they are. No settings. <code>wp adminkeep emails send --all --to=you@example.com<\/code> shows every one of them in your own inbox.<\/li>\n<li><strong>Contact Form<\/strong> \u2014 one simple form for any page: name, email and message, as a block or the <code>[adminkeep_contact_form]<\/code> shortcode. Messages are emailed to you through WordPress's own mailer, so the SMTP feature delivers them and Email Log shows whether each one went out, with the server's error if it did not. Works out of the box, protected by a WordPress nonce that needs no keys (not for sites that cache their pages), or by Cloudflare Turnstile or Google reCAPTCHA v3 with your own free keys. Nothing is stored. The form prints its own small style and script with itself, so nothing extra loads on other pages, and the spam check's script loads only on pages that show the form.<\/li>\n<\/ul>\n\n<h4>Admin<\/h4>\n\n<ul>\n<li><strong>User Registration Date<\/strong> \u2014 a sortable Registered column on the Users screen. WordPress records when every account was created but never shows it; this does, for every existing user, and newest-first sorting makes a wave of spam signups easy to spot. <a href=\"https:\/\/adminkeep.com\/guides\/wordpress-user-registration-date\/\">Guide<\/a><\/li>\n<\/ul>\n\n<h4>Content<\/h4>\n\n<ul>\n<li><strong>Duplicate<\/strong> \u2014 copy any post or page as a draft. Custom fields, taxonomies, the featured image and page builder layouts (Elementor, ACF) come along intact, and the original is never modified. <a href=\"https:\/\/adminkeep.com\/guides\/duplicate-page-wordpress\/\">Guide<\/a><\/li>\n<li><strong>Live Draft<\/strong> \u2014 rework a published page in a private working copy, then publish it over the original. Same ID, same URL, and the old version is kept as a revision. <a href=\"https:\/\/adminkeep.com\/guides\/edit-published-page-without-unpublishing\/\">Guide<\/a><\/li>\n<li><strong>Keep URL<\/strong> \u2014 rename or move a page and its old address keeps working, child pages included. Fills the gaps WordPress leaves for pages and leaves posts to core. <a href=\"https:\/\/adminkeep.com\/guides\/change-wordpress-slug-redirect\/\">Guide<\/a><\/li>\n<li><strong>Order<\/strong> \u2014 drag posts into the order you want on a dedicated Sort screen, one post type at a time. Lists that already ask for their own order, such as WooCommerce products and search results, are left alone. <a href=\"https:\/\/adminkeep.com\/guides\/reorder-wordpress-posts\/\">Guide<\/a><\/li>\n<li><strong>Replace Media<\/strong> \u2014 upload a new version of a file over the old one. Same file type keeps the same URL; a different type updates the posts that use it and redirects the old address. <a href=\"https:\/\/adminkeep.com\/guides\/replace-image-wordpress-same-url\/\">Guide<\/a><\/li>\n<\/ul>\n\n<h4>Performance<\/h4>\n\n<p>A feature you have not enabled registers zero hooks and loads zero assets.<\/p>\n\n<h4>Links<\/h4>\n\n<ul>\n<li><a href=\"https:\/\/adminkeep.com\/\">Website<\/a><\/li>\n<li><a href=\"https:\/\/adminkeep.com\/docs\/\">Documentation<\/a><\/li>\n<li><a href=\"https:\/\/adminkeep.com\/guides\/\">Guides<\/a><\/li>\n<\/ul>\n\n<h3>External services<\/h3>\n\n<p>Adminkeep connects to no outside service unless you switch on a feature that needs one and set it up. Two features can: SMTP sends your site's email through the mail server you enter, and the Contact Form uses the spam check you choose (its WordPress nonce option uses none). Nothing is sent to Adminkeep.<\/p>\n\n<p><strong>Cloudflare Turnstile<\/strong> (Contact Form, when you choose it). On pages that show the form, the visitor's browser loads Cloudflare's script from challenges.cloudflare.com, which receives the visitor's IP address and browser details in order to tell people from bots. When the visitor presses Send, your site sends Cloudflare your secret key and the check's one-time token, and nothing else, to confirm it. Terms: https:\/\/www.cloudflare.com\/website-terms\/ \u2014 Privacy policy: https:\/\/www.cloudflare.com\/privacypolicy\/<\/p>\n\n<p><strong>Google reCAPTCHA v3<\/strong> (Contact Form, when you choose it). On pages that show the form, the visitor's browser loads Google's script from www.google.com (and the code it needs from www.gstatic.com), which receive the visitor's IP address and browser details in order to score the visit. When the visitor presses Send, your site sends Google your secret key and the check's one-time token, and nothing else, to confirm it. Terms: https:\/\/policies.google.com\/terms \u2014 Privacy policy: https:\/\/policies.google.com\/privacy<\/p>\n\n<h3>WP-CLI<\/h3>\n\n<p>Everything on the Adminkeep settings screen, plus the Custom CSS, Header &amp; Footer Code, SMTP and Contact Form screens, can be done from a shell with <code>wp adminkeep<\/code>.<\/p>\n\n<pre><code>wp adminkeep feature list \u2014 every feature and whether it is on\nwp adminkeep feature enable disable_comments \u2014 switch a feature on (or `disable` it)\nwp adminkeep feature set order post_types=post,page \u2014 change a feature's settings\nwp adminkeep feature set two_factor roles=administrator,editor \u2014 choose who is asked for a login code\nwp adminkeep feature disable two_factor \u2014 a way back in if the site cannot send email\nwp adminkeep feature enable two_factor \u2014 switches it on and says where the recovery link was emailed\nwp adminkeep setting set hide_unused=true \u2014 change a plugin-level setting\nwp adminkeep comments purge \u2014 delete spam and trashed comments, in batches\nwp adminkeep css set site.css \u2014 replace the Custom CSS from a file\nwp adminkeep code set head analytics.html \u2014 replace one Header &amp; Footer Code box (head, body or footer) from a file\nwp adminkeep smtp set --host=smtp.example.com --port=587 \u2014 configure SMTP\nwp adminkeep smtp test you@example.com \u2014 send a test email and see the server's reply\nwp adminkeep emails send --all --to=you@example.com \u2014 see WordPress's own emails in the Nice Default Emails layout\nwp adminkeep smtp import wp-mail-smtp \u2014 copy the SMTP connection settings from WP Mail SMTP\nwp adminkeep contact-form set --provider=turnstile --turnstile-site-key=&lt;key&gt; \u2014 set up the contact form's spam protection (the secret goes in with `--turnstile-secret-stdin`)\nwp adminkeep contact-form get \u2014 the contact form's settings, and whether it is live\n<\/code><\/pre>\n\n<p>Run <code>wp help adminkeep<\/code> for the full reference. A change made here is cleaned and checked exactly as it is on the screen, and a mistyped value is refused rather than guessed at.<\/p>\n\n<!--section=installation-->\n<ol>\n<li>In your WordPress admin, go to <strong>Plugins \u2192 Add New Plugin<\/strong>, search for \"Adminkeep\" and click <strong>Install Now<\/strong>, then <strong>Activate<\/strong>.<\/li>\n<li>Open <strong>Settings \u2192 Adminkeep<\/strong>, or the <strong>Settings<\/strong> link under Adminkeep on the Plugins screen. Every feature starts <strong>off<\/strong>; switch on only the ones you want.<\/li>\n<li>To remove the plugin, deactivate and delete it as usual. Its settings and data are kept, so installing it again brings them back; to remove them as well, switch on <strong>Delete all Adminkeep data when the plugin is deleted<\/strong> under <strong>Settings \u2192 Adminkeep \u2192 Plugin settings<\/strong> before deleting. Nothing it changed while enabled outlives switching the feature off.<\/li>\n<\/ol>\n\n<p>Or with WP-CLI:<\/p>\n\n<pre><code>wp plugin install adminkeep --activate\n<\/code><\/pre>\n\n<!--section=faq-->\n<dl>\n<dt id=\"will%20this%20delete%20my%20comments%3F\"><h3>Will this delete my comments?<\/h3><\/dt>\n<dd><p>Not unless you ask it to. Turning Disable Comments on only hides them \u2014 a test asserts the comment rows are untouched after a full enable-and-disable cycle.<\/p>\n\n<p>There is a separate cleanup button that does delete, and it deletes <strong>spam and trashed comments only<\/strong> unless you tick the box to include approved ones. It shows the exact count, asks you to confirm, and cannot be undone.<\/p><\/dd>\n<dt id=\"can%20i%20turn%20it%20back%20off%3F\"><h3>Can I turn it back off?<\/h3><\/dt>\n<dd><p>Yes, instantly. There is never a migration to run or a repair step to find.<\/p>\n\n<p>The locks work through WordPress filters, so nothing was written to your database to undo \u2014 switch one off and your site is exactly as it was. The one exception is Two-Factor Login, which remembers trusted devices in user meta so they keep skipping the code. Switching it off leaves those entries where they are, doing nothing, and makes its recovery link stop working; deleting the plugin with \"Delete all Adminkeep data when the plugin is deleted\" switched on removes them. The Content features are deliberately different: they write the things you asked them to write. A copy you made, an order you saved, a file you replaced, a redirect recorded when you renamed a page \u2014 switching the feature off stops it doing any more, and leaves what it already did alone. Work you did on purpose should not disappear because you unticked a checkbox.<\/p><\/dd>\n<dt id=\"does%20this%20actually%20stop%20comment%20spam%20bots%3F\"><h3>Does this actually stop comment spam bots?<\/h3><\/dt>\n<dd><p>Yes. Bots usually POST straight to <code>wp-comments-post.php<\/code> without ever loading your page, so hiding the comment form does nothing. Adminkeep refuses those requests with a 403 before WordPress processes them, and refuses comment creation through the REST API as well.<\/p><\/dd>\n<dt id=\"is%20installation%20lockdown%20a%20security%20feature%3F\"><h3>Is Installation Lockdown a security feature?<\/h3><\/dt>\n<dd><p>Not exactly, and it would be dishonest to say otherwise. It is enforced in PHP, so anyone with filesystem, database or WP-CLI access can bypass it. It reliably stops accidents and casual changes \u2014 a client uploading a plugin zip from who knows where, or overwriting an installed plugin with one. Treat it as a policy guard, not a security boundary.<\/p><\/dd>\n<dt id=\"why%20not%20just%20use%20the%20disallow_file_mods%20constant%3F\"><h3>Why not just use the DISALLOW_FILE_MODS constant?<\/h3><\/dt>\n<dd><p>Because it cannot be switched off from the admin. Once it is in <code>wp-config.php<\/code> you need file access to undo it, which strands people. Installation Lockdown filters capabilities instead, so you can always turn it off from the settings screen. If you want the harder version, the constant is still there and this plugin does not interfere with it.<\/p><\/dd>\n<dt id=\"does%20the%20smtp%20feature%20work%20with%20gmail%20or%20microsoft%20365%3F\"><h3>Does the SMTP feature work with Gmail or Microsoft 365?<\/h3><\/dt>\n<dd><p>Gmail and Google Workspace: yes, with an app password. Microsoft 365 and Outlook.com: no \u2014 Microsoft now requires signing in through Microsoft (OAuth) for SMTP, which this feature does not support. A dedicated SMTP plugin is the better choice there.<\/p><\/dd>\n<dt id=\"where%20is%20my%20smtp%20password%20kept%3F\"><h3>Where is my SMTP password kept?<\/h3><\/dt>\n<dd><p>Encrypted in your site's database, which protects it in database backups. For the strongest setup define ADMINKEEP_SMTP_PASS (and the other ADMINKEEP_SMTP_* constants) in wp-config.php: values set there are not saved to the database, and the settings form does not display them.<\/p><\/dd>\n<dt id=\"does%20the%20email%20log%20store%20password-reset%20links%3F\"><h3>Does the email log store password-reset links?<\/h3><\/dt>\n<dd><p>They are removed before an email is stored, along with sign-in and account-activation links. The common link formats are covered, not every possible one, so treat it as a safeguard rather than a guarantee. If you would rather not store email content at all, Email Log has a setting to keep only the envelope \u2014 sender, recipient, subject and status \u2014 and switch content storage off. Two-Factor Login's code emails are always stored that way, whatever the setting.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20the%20email%20log%20if%20i%20switch%20the%20feature%20off%3F\"><h3>What happens to the email log if I switch the feature off?<\/h3><\/dt>\n<dd><p>Switching it off stops logging. What is already logged stays until you delete it, or delete the plugin with \"Delete all Adminkeep data when the plugin is deleted\" switched on. While it is off nothing new is recorded and the entries are not aged out, so if you want the log emptied, empty it first \u2014 from the Email Log screen, or with <code>wp adminkeep email-log purge --all<\/code> \u2014 and then switch the feature off.<\/p><\/dd>\n<dt id=\"what%20happens%20to%20my%20settings%20and%20data%20when%20i%20delete%20adminkeep%3F\"><h3>What happens to my settings and data when I delete Adminkeep?<\/h3><\/dt>\n<dd><p>They stay, unless you ask otherwise. Deleting the plugin keeps its settings, your Custom CSS and Header &amp; Footer Code, the SMTP and contact form settings, the email log, the Keep URL redirects and the devices Two-Factor Login remembers and its recovery link, so installing it again brings everything back. To remove all of it when the plugin is deleted, switch on \"Delete all Adminkeep data when the plugin is deleted\" under Settings \u2192 Adminkeep \u2192 Plugin settings, or run <code>wp adminkeep setting set delete_data=true<\/code>. Deactivating never deletes anything.<\/p><\/dd>\n<dt id=\"where%20does%20header%20%26%20footer%20code%20print%3F\"><h3>Where does Header &amp; Footer Code print?<\/h3><\/dt>\n<dd><p>On the front end of your site, on every page. The Head box goes inside <code>&lt;head&gt;<\/code>, before your theme's own styles and scripts. The Body open box goes just after <code>&lt;body&gt;<\/code> opens, on themes that support it (current themes do). The Footer box goes at the end of the page, after WordPress's own footer scripts. None of it is added to the admin, the login page, feeds or the REST API.<\/p>\n\n<p>Each box holds up to 64 KB. A snippet from an analytics or chat service is a few kilobytes; for anything larger, upload the script as a file and load it with <code>&lt;script src=\"\u2026\"&gt;&lt;\/script&gt;<\/code>. The code is printed exactly as you saved it, so check a snippet on a test page if you are unsure of it. Switching the feature off stops it printing and keeps the code.<\/p><\/dd>\n<dt id=\"where%20are%20contact%20form%20messages%20stored%3F\"><h3>Where are contact form messages stored?<\/h3><\/dt>\n<dd><p>The form itself stores nothing: each message is emailed to you and that is all. If Email Log is on, it keeps a copy for its retention period, with whether the email went out, and WordPress's own personal data export and erase tools find those copies by the visitor's email address.<\/p><\/dd>\n<dt id=\"why%20can%27t%20visitors%20see%20my%20contact%20form%3F\"><h3>Why can't visitors see my contact form?<\/h3><\/dt>\n<dd><p>It is hidden only while Cloudflare Turnstile or Google reCAPTCHA v3 is chosen without both of its keys saved. Open Settings \u2192 Contact Form and save them, or choose WordPress Nonce, which needs none. Until then, administrators see a note where the form will appear and visitors see nothing. If the screen says the last submission failed, it names the reason, such as a secret key the provider refused.<\/p><\/dd>\n<dt id=\"does%20the%20contact%20form%20work%20with%20page%20caching%3F\"><h3>Does the contact form work with page caching?<\/h3><\/dt>\n<dd><p>Not with the default spam protection, WordPress Nonce. A nonce expires within a day, so a page served from a cache for longer carries an expired one, and every message sent from it is refused. On a site with a caching plugin, a host-level cache or a CDN that caches pages, choose Cloudflare Turnstile or Google reCAPTCHA v3 under Settings \u2192 Contact Form.<\/p>\n\n<p>With either of those, yes. The form's markup is then the same for every visitor and carries no nonce or session, so a cached page keeps working. The spam check runs afresh on every send, and the message goes out through a REST request that is not cached.<\/p><\/dd>\n<dt id=\"does%20the%20contact%20form%20slow%20down%20my%20other%20pages%3F\"><h3>Does the contact form slow down my other pages?<\/h3><\/dt>\n<dd><p>No. The form carries its own small style and script, printed right after it, so there is no extra file to load on pages without the form, which suits page builders. Cloudflare's or Google's script is added only on pages that show the form.<\/p><\/dd>\n<dt id=\"what%20if%20i%20cannot%20get%20the%20two-factor%20login%20code%3F\"><h3>What if I cannot get the Two-Factor Login code?<\/h3><\/dt>\n<dd><p>After the password, the code screen shows the account's email address, partly hidden, and sends the code there when you press Email me the code, so you can tell the person who reads that mailbox before it arrives. The code is sent with wp_mail(), the same way WordPress sends password resets, so the SMTP feature delivers it. It always goes out in the Nice Default Emails layout, whether that feature is on or not. If password resets do not arrive either, the site cannot send email. Nobody in the chosen roles is signed in without the code, so a site whose email is down locks those users out until Two-Factor Login is switched off or email is fixed. See the next question for the ways back in.<\/p>\n\n<p>A code works once, for up to ten minutes from when it is sent, and a login attempt ends 30 minutes after the password at the latest; after either, the login starts again from the password form. Five wrong codes lock the code step for that account for 15 minutes, and each lock after that doubles the wait, up to six hours. Typing the password again does not get round it, and a device remembered with \"Remember this device\" is not affected. Asking for a new code does not give back tries already used.<\/p><\/dd>\n<dt id=\"i%20am%20locked%20out%20by%20two-factor%20login.%20how%20do%20i%20get%20back%20in%3F\"><h3>I am locked out by Two-Factor Login. How do I get back in?<\/h3><\/dt>\n<dd><p>There are three ways, and none of them needs you to log in first.<\/p>\n\n<ol>\n<li>The recovery link. When you switch Two-Factor Login on, a recovery link is emailed to you (to the site's administration email address when it is switched on with WP-CLI). The settings screen shows which address it went to, partly hidden, and tells you if the email could not be sent, so you can fix email before you log out. Opening the link shows a page with one button, Turn off Two-Factor Login; pressing it switches the feature off and keeps the roles you chose. The link does not expire, works once, and is replaced by a new one each time Two-Factor Login is switched on, so keep the newest email. Anyone who has the link can switch Two-Factor Login off, so treat that email like a password. When the link is used, every administrator of the site is emailed the time and the IP address it was used from.<\/li>\n<li>WP-CLI: <code>wp adminkeep feature disable two_factor<\/code>.<\/li>\n<li>wp-config.php: add <code>define( 'ADMINKEEP_DISABLE_TWO_FACTOR', true );<\/code>.<\/li>\n<\/ol>\n\n<p>The link does not sign anyone in; it only removes the code step, so your password is still needed.<\/p><\/dd>\n<dt id=\"which%20logins%20does%20two-factor%20login%20cover%3F\"><h3>Which logins does Two-Factor Login cover?<\/h3><\/dt>\n<dd><p>The main login screen, wp-login.php, which is where the code screen appears. Other login forms that use WordPress's own sign-in, such as WooCommerce's My Account or a custom form, cannot show the code screen, so they refuse users who owe a code and point them to the main login screen. A plugin that only moves the login screen to a different address works as usual. If a plugin replaces the login screen with its own form, the code screen cannot be reached on that site, so keep the recovery email: its link is then the way to switch Two-Factor Login off. On multisite, super admins are asked whenever administrators are, since they hold more power than any administrator of a site.<\/p>\n\n<p>The REST API, application passwords and XML-RPC are not asked for a code, because the apps and services that use them have no screen to type one into. An application password still works on its own. Disable XML-RPC is a separate feature.<\/p><\/dd>\n<dt id=\"can%20i%20manage%20adminkeep%20with%20wp-cli%3F\"><h3>Can I manage Adminkeep with WP-CLI?<\/h3><\/dt>\n<dd><p>Yes, since 1.5.0. <code>wp adminkeep feature list<\/code> shows every feature, and <code>wp help adminkeep<\/code> lists the commands for switching features, changing their settings, cleaning up comments, replacing the Custom CSS or the Header &amp; Footer Code, configuring SMTP and the contact form, and choosing whether the settings screen hides unused features for a user. If Installation Lockdown has locked you out of the admin, <code>wp adminkeep feature disable install_lock<\/code> is the way back in.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>2.6.0<\/h4>\n\n<ul>\n<li>New: Two-Factor Login, in Site Lock. Users in the roles you choose enter a six-digit code emailed to them after their password on the login screen. The code screen shows the account's address, partly hidden, and sends the code when the user presses \"Email me the code\". A code works once, for up to ten minutes, and a login waiting on its code ends 30 minutes after the password at the latest.<\/li>\n<li>New: five wrong codes lock the code step for that account for 15 minutes, doubling on repeat up to six hours. The login screen says how long is left, and a correct code clears the count. At most five code emails go to one user in ten minutes, and wrong codes are reported as failed logins, so login-limiting plugins count them.<\/li>\n<li>New: \"Remember this device\" skips the code on that browser for 30 days, or the number you set. A remembered device is not affected by a lock.<\/li>\n<li>New: switching Two-Factor Login on emails you a recovery link (to the site's administration email address from WP-CLI). The link opens a page with one button that turns Two-Factor Login off without logging in and keeps the roles you chose. It does not expire, works once, and is replaced each time the feature is switched on. The feature's panel shows which address holds the current link, partly hidden, or says that the email could not be sent, and <code>wp adminkeep feature enable two_factor<\/code> prints where it went. When the link is used, every administrator of the site is emailed the time and the IP address it was used from.<\/li>\n<li>New: <code>wp adminkeep feature disable two_factor<\/code> and the <code>ADMINKEEP_DISABLE_TWO_FACTOR<\/code> constant in wp-config.php also switch the code step off without logging in.<\/li>\n<li>New: on multisite, super admins are asked for a code whenever administrators are. Other login forms, such as WooCommerce's My Account, send users who owe a code to the main login screen. The REST API, application passwords and XML-RPC are not asked.<\/li>\n<li>New: the code email always goes out in the Nice Default Emails layout, whether or not that feature is on.<\/li>\n<li>Changed: the Email Log keeps only the envelope of a login-code or recovery-link email, never its body.<\/li>\n<li>Changed: deleting the plugin with \"Delete all Adminkeep data\" on also removes remembered devices, any login waiting on its code, any wrong-code lock and the recovery link.<\/li>\n<\/ul>\n\n<h4>2.5.0<\/h4>\n\n<ul>\n<li>New: Settings \u2192 Contact Form warns when WordPress Nonce is chosen on a site where a caching plugin looks active, since the nonce does not work on cached pages. The feature's state on the Adminkeep settings panel reads \"Live, page cache detected\". A new <code>adminkeep_contact_form_page_cache_detected<\/code> filter overrides the detection either way.<\/li>\n<li>Fixed: the Email Log preview was empty in the wordpress.org Live Preview.<\/li>\n<li>Fixed: the help for <code>wp adminkeep setting<\/code>, <code>contact-form<\/code> and <code>email-log list<\/code> no longer shows a summary cut off mid-sentence.<\/li>\n<\/ul>\n\n<h4>2.4.0<\/h4>\n\n<ul>\n<li>New: the Contact Form works out of the box, protected by a WordPress nonce: no keys and no outside service. Not for sites that cache their pages; choose Cloudflare Turnstile or Google reCAPTCHA there.<\/li>\n<li>Changed: the Contact Form's \"None (form hidden)\" choice is gone. To take the form down, remove its block or shortcode, or switch the feature off.<\/li>\n<li>Improved: the contact form's fields have a clean look of their own on themes that do not style form fields, such as Twenty Twenty-Five. Themes that do still win.<\/li>\n<li>Improved: the contact form's email says which page it was sent from on any page of the site, archives and author pages included.<\/li>\n<li>Changed: Settings \u2192 Contact Form shows how to place the form in a side box, and warns only when the form is hidden.<\/li>\n<li>Fixed: after switching the contact form's spam protection, the screen no longer shows the old provider's last error.<\/li>\n<\/ul>\n\n<h4>2.3.0<\/h4>\n\n<ul>\n<li>New: Contact Form, in the Email group. A name, email and message form for any page, as a block or the <code>[adminkeep_contact_form]<\/code> shortcode, emailed to you through WordPress's own mailer, so SMTP delivers it and Email Log shows whether it went out. Protected by Cloudflare Turnstile or Google reCAPTCHA v3 with your own keys, and hidden until they are set. Nothing is stored. The form carries its own small style and script, and the spam check's script loads only on pages that show the form. Settings under Settings \u2192 Contact Form, or <code>wp adminkeep contact-form get|set<\/code>.<\/li>\n<li>Changed: Nice Default Emails also dresses up the contact form's own emails.<\/li>\n<li>New: the readme has an External services section. Adminkeep connects to an outside service only when you switch on SMTP or the contact form and set it up.<\/li>\n<li>Improved: the Live Preview on wordpress.org opens on Email Log with a few sample emails.<\/li>\n<\/ul>\n\n<h4>2.2.0<\/h4>\n\n<ul>\n<li>Changed: deleting Adminkeep now keeps its settings and data, so installing it again brings them back. To remove everything when the plugin is deleted, switch on \"Delete all Adminkeep data when the plugin is deleted\" in the new Plugin settings tab under Settings \u2192 Adminkeep, or run <code>wp adminkeep setting set delete_data=true<\/code>.<\/li>\n<li>New: Header &amp; Footer Code can be read and saved over the REST API at <code>adminkeep\/v1\/header-footer-code<\/code>, so a site reached with an application password can have it updated. Boxes left out of a save are kept. The same permissions and checks apply as on the Header &amp; Footer Code screen.<\/li>\n<li>Improved: Custom CSS and Header &amp; Footer Code save without reloading the page.<\/li>\n<li>Fixed: deleting the plugin now also clears the scheduled Live Draft clean-up, and deleting it with its data also removes the marker Live Draft leaves on a merged copy.<\/li>\n<\/ul>\n\n<h4>2.1.0<\/h4>\n\n<ul>\n<li>New: edit Custom CSS on your live site. Edit CSS in the admin bar opens a code panel beside the page, and the page restyles as you type, the way the Customizer's CSS box did. Nothing is saved until you press Save. The panel stays open while you browse to other pages, until you close it. Appearance \u2192 Custom CSS opens it too, from its Live preview box.<\/li>\n<li>New: a Custom CSS setting, \"Show Edit CSS in the admin bar\", on by default. Untick it to hide the admin bar item; the panel still opens from Appearance \u2192 Custom CSS.<\/li>\n<li>New: Custom CSS can be read and saved over the REST API at <code>adminkeep\/v1\/custom-css<\/code>, so a site reached with an application password can have its CSS updated without logging in to wp-admin. The same permissions and checks apply as on the Custom CSS screen.<\/li>\n<li>Changed: the settings now list the feature groups as Site Lock, Appearance, Email, Admin and Content.<\/li>\n<\/ul>\n\n<h4>2.0.0<\/h4>\n\n<ul>\n<li>New: Header &amp; Footer Code, in Appearance. Three boxes (Head, Body open and Footer) for analytics and verification tags, tag managers and chat widgets, printed on the front end of every page exactly as saved. Each box shows who last changed it and when, and holds up to 64 KB. Only administrators who are allowed to post unfiltered HTML can open it.<\/li>\n<li>New WP-CLI commands: <code>wp adminkeep code get &lt;head|body|footer&gt;<\/code> prints one box, and <code>wp adminkeep code set &lt;head|body|footer&gt; [&lt;file&gt;]<\/code> replaces it from a file or standard input.<\/li>\n<li>Changed: Email Log now has its own item in the admin menu, right below where the Email Log plugin puts its own, with a different envelope icon so the two can be told apart. To keep it under Tools, tick \"Show Email Log under the Tools menu\" in the Email Log settings. Old Tools \u2192 Email Log links still work.<\/li>\n<li>Changed: the Adminkeep logo beside each feature screen's heading (Email Log, SMTP, Custom CSS, Header &amp; Footer Code, Sort, Replace file) opens that feature's own settings instead of the settings overview.<\/li>\n<li>Changed: <code>wp adminkeep css get<\/code> prints the CSS exactly as stored, with no newline added, so its output can be piped back into <code>css set<\/code> unchanged.<\/li>\n<li>Fixed: Custom CSS that starts with a blank line keeps it when saved from the screen.<\/li>\n<\/ul>\n\n<h4>1.10.0<\/h4>\n\n<ul>\n<li>New: Nice Default Emails, in Email. WordPress's own plain-text emails (password resets, new-user and comment notices, update reports, personal data requests, and multisite sign-ups; 25 in all) go out in one clean HTML layout headed by your site's name, with clickable links. WooCommerce and other plugins' emails, and anything already sent as HTML, are left as they are. No settings. Developers can keep an email plain with the <code>adminkeep_nice_emails_wrap<\/code> filter.<\/li>\n<li>New: Settings \u2192 SMTP can copy your SMTP connection settings from WP Mail SMTP in one click (server, port, encryption, username, password, From address and name). Only SMTP-mailer setups can be copied; values held in wp-config.php are kept. <code>wp adminkeep smtp import wp-mail-smtp [--dry-run]<\/code> does the same from a shell.<\/li>\n<li>New WP-CLI commands: <code>wp adminkeep emails list<\/code> and <code>wp adminkeep emails send &lt;id&gt;...|--all --to=&lt;email&gt;<\/code> send WordPress's own emails to one address so you can see them in a real inbox.<\/li>\n<li>Fixed: Disable File Editing now applies to super admins on a multisite network.<\/li>\n<\/ul>\n\n<h4>1.9.0<\/h4>\n\n<ul>\n<li>New: Username Privacy, in Site Lock. Author pages and the <code>?author=1<\/code> probe answer \"not found\" to visitors, the REST users list is closed to them, authors are left out of the sitemap (WordPress's own and Yoast SEO's) and out of embed previews, and author names in your theme stop linking to author pages. Logged-in users see everything as before; nothing is written.<\/li>\n<\/ul>\n\n<h4>1.8.1<\/h4>\n\n<ul>\n<li>Changed: \"Hide unused features\" is now one setting for the whole site instead of one per administrator. If any administrator had it on, it stays on.<\/li>\n<li>Changed: WP-CLI <code>wp adminkeep view<\/code> is replaced by <code>wp adminkeep setting get [&lt;key&gt;]<\/code> and <code>wp adminkeep setting set key=value<\/code>, the same shape as <code>feature set<\/code>, so plugin-level settings and feature settings read alike. <code>wp adminkeep setting set hide_unused=true<\/code> does what <code>view hide-unused --user=&lt;user&gt;<\/code> did, for the whole site.<\/li>\n<\/ul>\n\n<h4>1.8.0<\/h4>\n\n<ul>\n<li>Fixed: with Installation Lockdown on, \"View details\" for a plugin (from an update notice or a \"Requires:\" line) opened on an error. It now opens; installing from it is still blocked.<\/li>\n<li>New WP-CLI commands: <code>wp adminkeep view get|hide-unused|show-all --user=&lt;user&gt;<\/code> read and set whether the settings screen hides unused features for that user. (Replaced in 1.8.1 by <code>wp adminkeep setting set hide_unused=true|false<\/code>, site-wide.)<\/li>\n<\/ul>\n\n<h4>1.7.0<\/h4>\n\n<ul>\n<li>New: Email Log. Tools \u2192 Email Log lists the email your site sends, with recipient, subject and whether it was sent or failed, plus filters by status and date and a search; the sender, headers and content are one click away in the preview.<\/li>\n<li>New: Email Log filters sit in the list's top bar, with a Period filter (1 hour to 30 days, or a custom date range), and Screen Options shows or hides columns, including a From column that starts hidden.<\/li>\n<li>New: Preview a logged email in a window, rendered as it was sent, with its source a tab away. Scripts and remote images are blocked in the preview. Emails that carry both HTML and plain text show each in its own tab.<\/li>\n<li>The log records the sender an SMTP plugin really used, even one that sets it at send time such as FluentSMTP, with the sender's name.<\/li>\n<li>Password-reset, sign-in and activation links are removed before an email is stored, and you can switch content storage off.<\/li>\n<li>Old entries are deleted automatically (30 days by default; choose from 7 days up to 2 years) and the log is trimmed to the newest 10,000.<\/li>\n<li>New WP-CLI commands: <code>wp adminkeep email-log list|get|count|purge<\/code>.<\/li>\n<li>New: bring your history across from the Email Log plugin with <code>wp adminkeep email-log import email-log<\/code>. Emails are stored the way Adminkeep would have stored them (links removed, the retention setting respected), running it again only adds what is new, and the other plugin's log is left as it was.<\/li>\n<li>New: while the Email Log plugin is active, Tools \u2192 Email Log shows a \"Copy from Email Log\" button that does the same import from the screen, and says how many emails it copied and skipped.<\/li>\n<li>Works with or without the SMTP feature, and only administrators can open the log.<\/li>\n<li>Changed: Adminkeep's settings moved from their own top-level menu to <strong>Settings \u2192 Adminkeep<\/strong>. Old links and bookmarks still work, and the Plugins screen now has a Settings link.<\/li>\n<li>Fixed: saving the SMTP screen while ADMINKEEP_SMTP_* constants were set in wp-config.php cleared the saved values for those fields, so removing the constants later left SMTP without a host or password. The saved values are now kept, as <code>wp adminkeep smtp set<\/code> already did.<\/li>\n<\/ul>\n\n<h4>1.6.0<\/h4>\n\n<ul>\n<li>New: \"Hide unused features\" on the settings page. Switch it on and the menu lists only the features you use. Search still finds the rest. (Per administrator until 1.8.1 made it site-wide.)<\/li>\n<li>Improved: the Overview lists the features you have switched on first, and its \"features enabled\" count updates as soon as you save.<\/li>\n<li>Improved: the Registered column on the Users screen is narrower and shows a short month (Jan 10, 2024).<\/li>\n<li>Fixed: the SMTP test email was sent twice.<\/li>\n<li>Fixed: notices from other plugins were squeezed into the Adminkeep header on the settings page. They now sit above it.<\/li>\n<li>Fixed: after switching on Custom CSS or SMTP, the link to its screen appears as soon as you save, without reloading.<\/li>\n<li>Fixed: the settings filter only searched the first group.<\/li>\n<\/ul>\n\n<h4>1.5.0<\/h4>\n\n<ul>\n<li>New: WP-CLI. <code>wp adminkeep<\/code> switches features on and off, changes their settings, cleans up comments, replaces the Custom CSS, configures SMTP and sends a test email. Run <code>wp help adminkeep<\/code> to see every command.<\/li>\n<\/ul>\n\n<h4>1.4.0<\/h4>\n\n<ul>\n<li>New: SMTP, in a new Email group. Send your site's email through any SMTP server, with provider presets, a test email that shows the server's own reply, and settings that can live in wp-config.php.<\/li>\n<li>Changed: screens Adminkeep adds elsewhere in the admin (SMTP, Custom CSS, Order, Replace file) now carry a small Adminkeep mark at the start of the heading, linking to the Adminkeep settings. The settings page shows the mark too.<\/li>\n<\/ul>\n\n<h4>1.3.0<\/h4>\n\n<ul>\n<li>New: User Registration Date \u2014 a sortable Registered column on the Users screen, in a new Admin group. It uses the date WordPress already stores, so every existing user has one.<\/li>\n<li>Changed: the switch on each panel now reads \"Enable this feature\".<\/li>\n<li>Removed: the Overview note about Version Lock leaving in 1.1.0.<\/li>\n<\/ul>\n\n<h4>1.2.0<\/h4>\n\n<ul>\n<li>New: Custom CSS \u2014 site-level front-end CSS under Appearance \u2192 Custom CSS. It belongs to the site, not the theme, so it stays when you switch themes.<\/li>\n<li>Changed: internal names now match the plugin name. Settings and redirects are carried over automatically.<\/li>\n<li>Changed: plugin and author links now point to adminkeep.com.<\/li>\n<\/ul>\n\n<h4>1.1.0<\/h4>\n\n<ul>\n<li>Initial release.<\/li>\n<\/ul>","raw_excerpt":"Site lockdown and admin enhancements for WordPress: email log, custom CSS, disable comments and more. Every feature is off until you switch it on.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/370020","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=370020"}],"author":[{"embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/sajib1223"}],"wp:attachment":[{"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=370020"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=370020"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=370020"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=370020"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=370020"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/de.wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=370020"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}