IntelliPlan sends four types of lifecycle emails — a welcome message, a feedback request, a weekly newsletter, and admin-triggered one-off newsletters — plus transactional emails such as deadline reminders. All of them flow through a single email path: either Resend (preferred) or a generic SMTP server as a fallback. Getting email right requires more than an API key: you need a verified sending domain with correct DNS records, a physical postal address in every marketing email, and reply-to addresses that actually receive mail. This page walks through all of it.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/UAnirudh/IntelliPlan/llms.txt
Use this file to discover all available pages before exploring further.
Choosing a Sending Path
IntelliPlan checks forRESEND_API_KEY at startup. If it is set, Resend handles all outgoing mail. If it is not set, IntelliPlan falls back to SMTP using the SMTP_* variables. The two paths are mutually exclusive — you cannot use both simultaneously.
Resend (Recommended)
Simple API, first-class deliverability, excellent domain verification UI, and a generous free tier. Preferred for all IntelliPlan deployments.
SMTP Fallback
Use any SMTP server — Gmail with an App Password, SendGrid, Postmark, or your own mail server. No additional libraries needed.
Resend Setup
Create an API key
Sign in at resend.com and go to API Keys → Create API Key. Copy the key.
.env
Add and verify the sending domain
Go to Resend → Domains → Add Domain. Use a subdomain rather than your apex domain.
intelliplan.tech has a CNAME at the apex pointing at Railway. DNS does not permit other record types alongside an apex CNAME, so adding SPF/DKIM records at the apex would conflict. Use the subdomain send.intelliplan.tech — this is Resend’s own recommendation and avoids any DNS conflict.- In Resend, add
send.intelliplan.tech(or your equivalent subdomain). - Resend will show you DKIM and SPF records. Publish them as ordinary subdomain records at your registrar — no apex records, no nameserver change required.
- Wait for Resend to confirm the records are live (usually under 10 minutes).
SMTP Fallback Setup
Used only whenRESEND_API_KEY is not set.
.env
Reply-To Configuration
All lifecycle emails are sent from anoreply@ address, but they explicitly invite students to reply. Without correct reply-to setup, every student reply bounces silently.
.env
CAN-SPAM Compliance: Postal Address
.env
Lifecycle Email Types
IntelliPlan sends four email variants. Every send passesintelliplan.email.eligibility.is_marketing_eligible, which refuses to send to accounts with unknown age, users under 13 without parental consent, non-student roles, or suppressed addresses. Sends are deduplicated on (user_id, email_key) in the email_sends table — a double cron fire cannot double-send.
Welcome (welcome)
Welcome (welcome)
Trigger: Cron, accounts created in the last 36 hours.Consent: Transactional — no marketing opt-in required.MARKETING_POSTAL_ADDRESS: Not required.The welcome email is sent once per new account. It does not require marketing consent and is the only lifecycle email that sends without
MARKETING_POSTAL_ADDRESS set.Feedback Request (feedback_v2)
Feedback Request (feedback_v2)
Trigger: Cron, accounts that are 7–8.5 days old and have real activity (not dormant signups).Consent: Requires
marketing_emails_opt_in = True.Key: feedback_v2 — deduplicated so a daily sweep cannot ask someone twice.The feedback email invites students to answer a few short questions about their experience. The 7-day window and activity requirement are quality heuristics — to reach everyone who has given consent regardless of these filters, use the admin blast endpoint:Weekly Newsletter (newsletter_YYYY_wWW)
Weekly Newsletter (newsletter_YYYY_wWW)
One-Off Newsletter (newsletter_YYYY_MM)
One-Off Newsletter (newsletter_YYYY_MM)
Cron Schedule
Two cron jobs drive lifecycle email delivery. Both useCRON_SECRET for authentication (pass as X-Cron-Secret or X-Cron-Token header, or ?secret= query parameter).
| Job | Endpoint | Schedule | Railway Expression |
|---|---|---|---|
| Lifecycle emails (welcome + feedback) | POST /cron/lifecycle-emails | Daily at 16:00 UTC | 0 16 * * * |
| Weekly newsletter | POST /cron/weekly-newsletter | Thursdays at 16:00 UTC | 0 16 * * 4 |
Unsubscribe
IntelliPlan provides a one-click unsubscribe endpoint that works without being logged in:marketing_emails_opt_in = False on the user and adds the email address (not the user ID) to email_suppressions. This means deleting and recreating an account does not reset the suppression — the address stays suppressed. Deadline reminders are transactional and are deliberately unaffected by unsubscribe.
Marketing Eligibility Rules
Every marketing send (feedback, newsletter) passesintelliplan.email.eligibility.is_marketing_eligible. A send is refused if any of the following apply:
Eligibility rules checked before every marketing send
Eligibility rules checked before every marketing send
| Rule | What triggers a refusal |
|---|---|
| Age gate | User’s age is unknown |
| Under-13 gate | User is under 13 without verified parental consent |
| Consent | marketing_emails_opt_in is not True |
| Undated consent | Consent was recorded without a timestamp |
| Role gate | Account is not a student role |
| Suppression list | Email address is in email_suppressions |
Preflight Check
Before sending to any users, run the preflight endpoint to verify your configuration:- Whether
RESEND_API_KEYor SMTP credentials are set - Whether
RESEND_FROM/SMTP_FROMuses a verified domain - Whether
MARKETING_REPLY_TOandSUPPORT_EMAILpoint at addresses that can receive mail - Whether
MARKETING_POSTAL_ADDRESSis set - Any other configuration issues that would block a send