Skip to main content

Nobody can log in, or emails do not arrive

Most login problems are really email problems, because members (and admins, with ADMIN_AUTH=table) log in by a link sent by email. This page covers both. It is for whoever runs the server. Start with the configuration check (Troubleshooting) and the log (Logs and health checks).

Nobody stays logged in​

A person logs in and is back at the login page on the next click.

  • The site is served over plain http. In production (the default NODE_ENV=production) the login cookie is marked Secure, and browsers do not keep a Secure cookie that arrived over plain http. Serve the site over HTTPS: Put it behind HTTPS. Also make sure the proxy passes the request on to the site, as the browser sees it, over HTTPS.
  • SESSION_STORE=memory. Sessions are then kept in the server's memory. Every restart (including every update) logs everyone out, and with more than one process each has its own memory. The configuration check warns about it. Use database (the default on Node), or redis. See Sessions.
  • Two host names. The cookie belongs to one exact host name. Logging in at choir.example.org and then visiting www.choir.example.org looks like being logged out. Send one name to the other at your proxy.
  • Redis is not reachable. The log shows [sessions] redis error: ....
  • Time limits. An admin session lasts 24 hours (ADMIN_SESSION_HOURS) and a member's 30 days (MEMBER_SESSION_DAYS).

The admin login always fails​

The login page answers Invalid credentials, or says "The admin account is not set up on the server (ADMIN_USERNAME and ADMIN_PASSWORD)."

  • The username and password are not both set. With ADMIN_AUTH=env (the default) the one admin is the ADMIN_USERNAME and ADMIN_PASSWORD from the environment. The second message above means one is empty. The check lists "ADMIN_USERNAME and ADMIN_PASSWORD are not set: nobody can log in to the admin panel".
  • The values did not arrive. See My .env file is ignored.
  • The username is compared without regard to capitals and surrounding spaces. The password is exact. A password with #, $, quotes or spaces may need quotes in the environment file.
  • ADMIN_AUTH is mistyped. It must be env or table. Any other value shows ADMIN_AUTH is "...": use env or table. Nobody can log in to the admin panel until it is one of them.
  • ADMIN_AUTH=table and email is down. Admins then get a login link by email, and only the username and password get anyone in if email does not work. If you have neither, add an admin from the command line: see Add the first admin, and get back in when locked out.

Members ask for a link on the member login page, admins on the admin login page. The page always answers "If that address belongs to ..., a login link is on its way", whether or not the address is known, so you cannot tell from the page. Look in the log.

What the log showsCause and fix
[email] To: ... followed by the messageEMAIL_PROVIDER=log. The message went to the log, not out. The link is in the lines below. Set a real provider: Email providers.
Member login link for ... not sent: email is off (or Admin login link ...)EMAIL_PROVIDER=none, or no EMAIL_FROM set (unconfigured).
Resend rejected the email: ... (also SendGrid, Postmark, Mailgun, SES)The provider received the message and refused it. The rest of the line is its reason: an unverified sender address or domain, a key without permission, an account still in a "sandbox", or a limit reached.
SMTP send failed: ...The mail server refused or could not be reached: host, port, SMTP_SECURE, user and password.
Nothing at allSee below.

If the log shows nothing:

  • The person was asked too often. A link is sent at most once a minute and five an hour per account. Wait.
  • The address is not on file. An address that is not a member (or an active member, with the portal on) or admin gets no email and the same answer. Check it in the admin panel under Members (or Admins), including spelling.
  • The message is in spam. Check the spam folder. A sender domain without SPF and DKIM set up with the provider is often filtered. Verify the domain with your provider.
  • The provider accepted it but the sender is not verified. Some providers accept and then drop mail from unverified senders. Check their dashboard's activity log.
  • The link has already been used or expired. It lasts 15 minutes and works once. Mail scanners at some organisations open links in advance; the link page therefore needs a click.

In production the link is made from SITE_URL and nothing else. Whatever it says is wrong comes from there.

  • It points to the wrong address. Correct SITE_URL (include https://, no path, no trailing slash) and restart.
  • Asking for a link gives "Server error". In production SITE_URL must be set, or the site cannot build the link. The log shows SITE_URL is not set, and the configuration check shows "SITE_URL is not set: emailed login links need the site address".
  • It points to localhost. SITE_URL was left at a trial value.

Contact form messages do not arrive​

The contact form emails the message to CONTACT_FORM_TO, or, if that is not set, to the public contact email in Site Settings > Contact. When it cannot be emailed, the message is not lost: it is kept for you.

  1. Log in to the admin panel and open Messages. Messages that could not be emailed are there.
  2. If they are there, email is the problem: see the table above. The message is kept when there is no address to send to (neither CONTACT_FORM_TO nor a public contact email), when email is log, none or incomplete, or when the provider refused it.
  3. If the form says "The contact form is turned off", it has been switched off in Site Settings.

"Security verification failed"​

The contact form says Security verification failed. Please try again. The bot check (Stop spam with a bot check) refused the visitor's token.

  • CAPTCHA_SITE_KEY and CAPTCHA_SECRET_KEY do not belong together, or belong to another site or provider.
  • Your domain is not in the allowed list in the provider's dashboard.
  • A browser extension or a content security policy blocks the provider's script. Your proxy's Content-Security-Policy must allow it: see Security.
  • The log line turnstile verification failed: [ 'invalid-input-secret' ] (or hcaptcha, recaptcha) gives the provider's own error codes.
  • Unknown CAPTCHA_PROVIDER "x" in the log: the name must be none, turnstile, hcaptcha or recaptcha.

To switch the check off while you fix it, set CAPTCHA_PROVIDER=none.

Some announcement emails are not sent on Cloudflare​

Announcements are sent in batches of EMAIL_BATCH_SIZE people (default 15), and the admin page keeps asking for the next batch until it is done. A Cloudflare Worker on the free plan may make only 50 outgoing requests for each request it handles, so a batch size much above 15 means the Worker hits that limit and the rest of the batch is not sent. Set EMAIL_BATCH_SIZE to 15 or less on the free plan. See Cloudflare: limits and logs.

If sending reports "Email is not set up on the server, so nothing was sent", the provider is none or has no sender address. On any platform, EMAIL_PER_SECOND (default 8) sets how fast a batch is sent. If your provider limits you to fewer messages a second (Amazon SES asks the site to slow down), the messages it refuses are not retried, and the log has no line for them. They are counted as not delivered, and the announcement or message list names the addresses ("Could not send to ..." or "could not be delivered"). Lower EMAIL_PER_SECOND to your provider's limit, then send to those people again.

Announcements will not send because SITE_URL is not set​

Every announcement and bulk message carries a link to stop that kind of email, and the link is made from SITE_URL. In production, if SITE_URL is not set, the site cannot build it:

  • sending an announcement to members fails, and the log has SITE_URL is not set;
  • sending a message from the donors or tickets pages fails with "Something went wrong sending the message.", and the log has Mailings: sending the message failed: followed by SITE_URL is not set. A test copy fails the same way.

Set SITE_URL (with https://, no path), restart, and send again.