Skip to content

Latest commit

 

History

History
210 lines (148 loc) · 9.26 KB

File metadata and controls

210 lines (148 loc) · 9.26 KB

Setup: Gmail SMTP

How to wire pingme to a Gmail account so your tools can email you. Replace you@gmail.com everywhere with your own Gmail address.

Why an "app password" instead of your real password? Google does not let third-party programs sign in with your account password directly. Instead you generate a one-purpose 16-character password that only works for SMTP. You can revoke it any time without changing your real password, and if it leaks, attackers cannot use it to read your inbox or change your settings.


Step 1 — Enable 2-Step Verification on the Google account

App passwords require 2-Step Verification (2FA) to be enabled first.

  1. Sign in to https://myaccount.google.com/ as you@gmail.com. Make sure the account picker (top-right avatar) shows the address you want pingme to send FROM, not your personal address.
  2. Left sidebar → Security & sign-in (Google occasionally renames this; on older UIs it may just be "Security").
  3. Find the section about how you sign in. Look for an entry named 2-Step Verification (sometimes labeled "2-Step Verification" or "2-Factor Authentication").
  4. Click it and follow the prompts to set it up. Recommended methods:
    • Google Authenticator app (works offline; recommended)
    • SMS code (works but less secure)
    • Hardware security key (most secure, optional)

Once 2-Step Verification shows "On" on the Security & sign-in page, continue to Step 2.

If you don't see "2-Step Verification" anywhere on the Security & sign-in page, the account may be a Google Workspace (org-managed) account where the admin has disabled it. In that case, ask your Workspace admin, or use a personal @gmail.com account instead.


Step 2 — Generate the App Password

  1. Go directly to https://myaccount.google.com/apppasswords. If the page says "The setting you are looking for is not available", it usually means 2-Step Verification is not yet active — go back to Step 1.

  2. App name field: enter something descriptive, e.g. pingme, atomx-toolkit, or the hostname of the machine that will use it (e.g. binks-pingme). This name is just a label so you can identify and revoke it later — it does not affect functionality.

  3. Click Create.

  4. A yellow box pops up with a 16-character password displayed in four groups of four, like:

    abcd efgh ijkl mnop
    
  5. Copy this password now. Once you close the box you cannot view it again — you would have to delete it and generate a new one.

  6. The spaces are cosmetic. Both abcdefghijklmnop and abcd efgh ijkl mnop work, but strip the spaces before pasting it into config files — it is the cleanest form and avoids any tool that might mishandle whitespace.

Where to revoke later: the same apppasswords page lists every app password you have ever created. Click the trash icon next to one to revoke it. Revoke immediately if a machine is decommissioned, an env file leaks, or you no longer need the integration.


Step 3 — Tell pingme where the credentials live

You have two options. Pick one (env vars OR dotenv file). Most people use the dotenv file because it survives across shell sessions without needing to add lines to ~/.bashrc.

Option A: dotenv file at ~/.config/pingme/smtp.env

mkdir -p ~/.config/pingme
cat > ~/.config/pingme/smtp.env <<'EOF'
PINGME_SMTP_USER=you@gmail.com
PINGME_SMTP_APP_PASSWORD=abcdefghijklmnop
EOF
chmod 600 ~/.config/pingme/smtp.env

Replace abcdefghijklmnop with the 16-character password from Step 2.

The chmod 600 makes the file readable only by you. Important — the password is enough for someone to send email as your account.

Option B: environment variables

Add to ~/.bashrc or ~/.zshrc:

export PINGME_SMTP_USER=you@gmail.com
export PINGME_SMTP_APP_PASSWORD=abcdefghijklmnop

Then source ~/.bashrc or open a new shell.

Env vars take precedence over the dotenv file per-key. If you set PINGME_SMTP_USER in env but leave PINGME_SMTP_APP_PASSWORD in the dotenv file only, that combination still works.


Step 4 — Test that pingme can read the credentials

Install pingme into a scratch venv and check the credentials chain resolves before sending anything:

uv venv /tmp/pingme-test
uv pip install --python /tmp/pingme-test/bin/python \
  "git+https://github.com/wuwenrui555/pingme.git@v0.1.2"

/tmp/pingme-test/bin/python -c "
from pingme import load_smtp_credentials, SmtpCredentialsMissing
creds = load_smtp_credentials()
if isinstance(creds, SmtpCredentialsMissing):
    print('FAIL: credentials not found')
else:
    print(f'OK: user={creds.user}, host={creds.host}, port={creds.port}, transport={creds.transport}')
"

Expected output:

OK: user=you@gmail.com, host=smtp.gmail.com, port=465, transport=ssl

If you see FAIL: credentials not found, the env vars aren't set AND the dotenv file isn't readable. Double-check Step 3.


Step 5 — Send a real test email

Send an email to yourself. Open Gmail in another tab so you can watch for it in real time.

/tmp/pingme-test/bin/python -c "
from pingme import load_smtp_credentials, send_email
creds = load_smtp_credentials()
send_email(
    creds=creds,
    recipients=['you@gmail.com'],   # send to yourself
    subject='[pingme] hello',
    body='If you can read this, pingme works on this machine.\n',
)
print('send_email returned (no exception)')
"

Expected:

  • The shell prints send_email returned (no exception).
  • Within ~10 seconds, an email arrives in you@gmail.com's inbox with subject [pingme] hello and the test body.

If the script prints fine but no email arrives:

  • Check Gmail's Sent folder. If the message is there, the send succeeded; the issue is on the receive side (spam folder? wrong recipient address?).
  • Check Gmail's Spam folder. Self-sends sometimes get filtered.
  • Check the recipient address you typed.

If the script logs an ERROR line about SMTP failure, the credentials or network are wrong:

  • Wrong password → SMTPAuthenticationError: 535 ... Username and Password not accepted. Re-check that you copied all 16 characters of the app password and pasted it into PINGME_SMTP_APP_PASSWORD (NOT the regular Google account password).
  • Network/firewall blocking port 465 → OSError or timeout. Check outbound 465 is reachable from the machine. Some networks block it (rare); try PINGME_SMTP_TRANSPORT=starttls + PINGME_SMTP_PORT=587 to switch to the STARTTLS path on port 587 instead. (Most networks let one of the two through.)

Step 6 — Set up a recipients directory (for real consumers)

The recipients parameter to send_email can be a hardcoded list (as in Step 5) or, more commonly, resolved from per-event text files that you can edit at runtime without touching code.

mkdir -p ~/.config/myapp/recipients
cat > ~/.config/myapp/recipients/alerts.txt <<'EOF'
# One email per line. Lines starting with # are comments.
# Blank lines are ignored.
you@gmail.com
EOF
cat > ~/.config/myapp/recipients/default.txt <<'EOF'
# Fallback when an event-specific file is empty.
you@gmail.com
EOF

Then your tool resolves recipients per event:

from pathlib import Path
from pingme import resolve_recipients, load_smtp_credentials, send_email

creds = load_smtp_credentials()
res = resolve_recipients("alerts", Path("~/.config/myapp/recipients").expanduser())
send_email(
    creds=creds,
    recipients=res.emails,
    subject="[myapp] disk full",
    body="binks /var at 96% used",
)

Hot-reload: editing alerts.txt takes effect on the next call to resolve_recipients — no process restart needed.


Step 7 — Clean up the test venv

rm -rf /tmp/pingme-test

(or trash-put /tmp/pingme-test if you have trash-cli installed, matching the binks convention.)


Troubleshooting summary

Symptom Likely cause Fix
apppasswords page says "setting not available" 2FA not enabled Step 1
Step 4 prints FAIL: credentials not found env vars unset and no dotenv file Step 3
SMTPAuthenticationError: 535 wrong app password or pasted real password regenerate in Step 2
Connection unexpectedly closed: timed out on send very unusual on the default SSL@465 path; usually means the port is blocked at the firewall TCP-probe bash -c "</dev/tcp/smtp.gmail.com/465". If unreachable, the network is filtering 465 — try PINGME_SMTP_TRANSPORT=starttls + PINGME_SMTP_PORT=587. (Note: STARTTLS on 587 is the OPPOSITE failure mode — it's commonly broken by SMTP-aware middleboxes that interfere with the upgrade handshake even when TCP/587 is reachable.)
Script succeeds, no email arrives spam folder, or check Sent folder Gmail webview
Email arrives but body is empty body argument missed \n and got truncated always end body with newline

Where credentials live, summary

File Purpose Permissions
~/.config/pingme/smtp.env SMTP user + app password (default location) chmod 600
~/.config/myapp/recipients/<event>.txt who to email per event normal (644 OK)
~/.config/myapp/recipients/default.txt fallback recipients normal

The recipient files are operator-curated and meant to be readable — team members might cat them to confirm subscriptions. The credential file is secret and should be 600.