Skip to main content

ADR-063: Email Infrastructure and Alias Configuration

Status: Accepted Date: 2026-01-11 Deciders: Hal Casteel (CTO) Related ADRs:


Context

CODITECT requires functional email addresses for pilot launch operations including:

  • User support communications
  • Pilot program coordination
  • Security vulnerability reports
  • Privacy/GDPR requests
  • Transactional emails (invitations, purchase confirmations, password resets)

The primary corporate domain is az1.ai with all emails routing to 1@az1.ai. CODITECT product emails need to be available at coditect.ai domain with forwarding to az1.ai.


Decision

Email Architecture

CODITECT Product Emails (coditect.ai)

│ Alias/Forward

AZ1.AI Corporate Email (1@az1.ai)

│ Google Workspace

Primary Inbox (Google Workspace)

Required Email Aliases

CODITECT AddressForwards ToPurpose
support@coditect.ai1@az1.aiUser support tickets
pilot@coditect.ai1@az1.aiPilot program coordination
security@coditect.ai1@az1.aiSecurity vulnerability reports
privacy@coditect.ai1@az1.aiPrivacy/GDPR requests
noreply@coditect.aiN/A (SendGrid)Transactional emails (outbound only)
admin@coditect.ai1@az1.aiAdministrative communications
billing@coditect.ai1@az1.aiBilling inquiries
feedback@coditect.ai1@az1.aiProduct feedback

Transactional Email (Outbound)

Provider: SendGrid Sender: CODITECT <noreply@coditect.ai> Use Cases:

  • Team invitation emails
  • Purchase confirmation
  • License activation
  • Password reset
  • Workstation provisioning notifications

Implementation

Step 1: Configure DNS Records for coditect.ai

MX Records (for receiving - optional if using forwarding service):

coditect.ai.  IN  MX  10  mx1.improvmx.com.
coditect.ai. IN MX 20 mx2.improvmx.com.

SPF Record (for sending via SendGrid):

coditect.ai.  IN  TXT  "v=spf1 include:sendgrid.net include:_spf.google.com ~all"

DKIM Record (SendGrid-provided):

s1._domainkey.coditect.ai.  IN  CNAME  s1.domainkey.u12345678.wl.sendgrid.net.
s2._domainkey.coditect.ai. IN CNAME s2.domainkey.u12345678.wl.sendgrid.net.

DMARC Record:

_dmarc.coditect.ai.  IN  TXT  "v=DMARC1; p=quarantine; rua=mailto:dmarc@coditect.ai; pct=100"

Step 2: Configure Email Forwarding

Option A: ImprovMX (Recommended for aliases)

  1. Sign up at https://improvmx.com
  2. Add domain: coditect.ai
  3. Verify domain ownership via DNS TXT record
  4. Add aliases:
    support@coditect.ai → 1@az1.ai
    pilot@coditect.ai → 1@az1.ai
    security@coditect.ai → 1@az1.ai
    privacy@coditect.ai → 1@az1.ai
    admin@coditect.ai → 1@az1.ai
    billing@coditect.ai → 1@az1.ai
    feedback@coditect.ai → 1@az1.ai
  5. Add MX records to DNS

Option B: Google Workspace Routing (if coditect.ai added to Workspace)

  1. Admin Console → Apps → Google Workspace → Gmail → Routing
  2. Add routing rule for each alias
  3. Configure delivery to 1@az1.ai

Step 3: Configure SendGrid for Transactional Email

1. Create SendGrid Account

# Store API key in Secret Manager
echo -n "SG.xxx..." | gcloud secrets create sendgrid-api-key \
--data-file=- \
--replication-policy=automatic \
--project coditect-cloud-infra

2. Authenticate Domain in SendGrid

  • Add coditect.ai to SendGrid
  • Configure CNAME records for DKIM
  • Verify domain authentication

3. Configure Django Backend

# backend/coditect_license/settings.py

# Email Configuration
EMAIL_BACKEND = os.environ.get(
'EMAIL_BACKEND',
'django.core.mail.backends.smtp.EmailBackend'
)

# SendGrid Settings
SENDGRID_API_KEY = os.environ.get('SENDGRID_API_KEY')
EMAIL_HOST = 'smtp.sendgrid.net'
EMAIL_PORT = 587
EMAIL_USE_TLS = True
EMAIL_HOST_USER = 'apikey'
EMAIL_HOST_PASSWORD = SENDGRID_API_KEY

# Default sender
DEFAULT_FROM_EMAIL = 'CODITECT <noreply@coditect.ai>'
SERVER_EMAIL = 'CODITECT System <system@coditect.ai>'

4. Kubernetes Secret

# kubernetes/base/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: email-secrets
namespace: coditect-dev
type: Opaque
stringData:
SENDGRID_API_KEY: ${SENDGRID_API_KEY}
EMAIL_FROM: "CODITECT <noreply@coditect.ai>"

Step 4: Email Service Implementation

# backend/core/services/email.py

from django.conf import settings
from django.core.mail import send_mail
from django.template.loader import render_to_string
import logging

logger = logging.getLogger(__name__)

class EmailService:
"""Email service for CODITECT transactional emails."""

@staticmethod
def send_invitation_email(
to_email: str,
inviter_name: str,
team_name: str,
accept_url: str
) -> bool:
"""Send team invitation email."""
subject = f"{inviter_name} invited you to join {team_name} on CODITECT"

context = {
'inviter_name': inviter_name,
'team_name': team_name,
'accept_url': accept_url,
}

html_message = render_to_string('emails/invitation.html', context)
plain_message = render_to_string('emails/invitation.txt', context)

try:
send_mail(
subject=subject,
message=plain_message,
from_email=settings.DEFAULT_FROM_EMAIL,
recipient_list=[to_email],
html_message=html_message,
)
logger.info(f"Invitation email sent to {to_email}")
return True
except Exception as e:
logger.error(f"Failed to send invitation email: {e}")
return False

@staticmethod
def send_welcome_email(to_email: str, user_name: str) -> bool:
"""Send welcome email after registration."""
# Implementation similar to above
pass

@staticmethod
def send_workstation_ready_email(
to_email: str,
workstation_name: str,
dashboard_url: str
) -> bool:
"""Send notification when workstation is ready."""
# Implementation similar to above
pass

Step 5: Verification Checklist

# 1. Verify DNS records
dig MX coditect.ai
dig TXT coditect.ai
dig TXT _dmarc.coditect.ai
dig CNAME s1._domainkey.coditect.ai

# 2. Test email forwarding
echo "Test from CLI" | mail -s "Test forwarding" support@coditect.ai

# 3. Test SendGrid sending
python -c "
from django.core.mail import send_mail
send_mail(
'Test Email',
'This is a test from CODITECT.',
'noreply@coditect.ai',
['test@example.com'],
)
"

# 4. Check email deliverability
# Use https://www.mail-tester.com/ to verify SPF/DKIM/DMARC

Email Templates

Location

backend/templates/emails/
├── base.html # Base template with branding
├── invitation.html # Team invitation
├── invitation.txt # Plain text version
├── welcome.html # Welcome after signup
├── workstation-ready.html # Workstation provisioned
├── purchase-confirm.html # License purchase confirmation
└── password-reset.html # Password reset link

Template Example (invitation.html)

{% extends "emails/base.html" %}
{% block content %}
<h1>You've been invited to CODITECT</h1>
<p>{{ inviter_name }} has invited you to join <strong>{{ team_name }}</strong> on CODITECT.</p>
<p>
<a href="{{ accept_url }}" class="button">Accept Invitation</a>
</p>
<p>This invitation expires in 7 days.</p>
{% endblock %}

Security Considerations

  1. No Email Credentials in Code - All secrets in GCP Secret Manager
  2. SPF/DKIM/DMARC - Prevents email spoofing and phishing
  3. TLS Required - All email transmission encrypted
  4. Rate Limiting - SendGrid handles abuse prevention
  5. Audit Logging - All transactional emails logged
  6. Unsubscribe Headers - Required for CAN-SPAM compliance

Consequences

Positive

  • Single inbox (1@az1.ai) for all CODITECT emails - simplified management
  • Professional email addresses for each function (support@, security@, etc.)
  • SendGrid handles deliverability, reputation, and scaling
  • Email authentication prevents spoofing

Negative

  • Dependency on external services (ImprovMX, SendGrid)
  • Monthly cost for SendGrid (~$15-50/month for pilot scale)
  • DNS propagation delays when making changes

Risks

  • SendGrid service outage would block transactional emails
  • Mitigation: Email queue with retry logic, fallback to SMTP

Monitoring

  1. SendGrid Dashboard - Delivery rates, bounces, spam reports
  2. GCP Cloud Monitoring - Email service errors in application logs
  3. ImprovMX Dashboard - Forwarding success/failures

Cost

ServiceMonthly CostNotes
ImprovMXFree (up to 25 aliases)Or $9/mo for premium
SendGridFree (100 emails/day)Or $15/mo for 40K/mo
Total$0-24/monthPilot scale

References


Document Owner: Hal Casteel, Founder/CEO/CTO, AZ1.AI INC Last Updated: January 11, 2026