19 Commits
Author SHA1 Message Date
westfarn 0ba6710faa Update company_site/financial/templates/financial/subscription_new.html for Stripe invoices (#23)
CI / test (pull_request) Successful in 13s
Unit Tests / test (pull_request) Successful in 11s
2026-07-31 12:01:59 -07:00
westfarn 70181ceda1 Update company_site/financial/templates/financial/subscription_detail.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn ea382cf4ba Update company_site/financial/templates/financial/invoices.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 2332caca08 Update company_site/financial/templates/financial/invoice_new.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 5596a87cc7 Update company_site/financial/templates/financial/invoice_detail.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 3fc73cbf56 Update company_site/financial/templates/emails/invoice_pay_link.txt for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 8630eb7755 Update company_site/financial/templates/emails/invoice_pay_link.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn cd41c75920 Update company_site/financial/stripe_billing.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 67acda869a Update company_site/financial/migrations/0016_billing_invoices_subscriptions.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn c66bfa39f0 Update company_site/financial/invoice_views.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 25bf9c6193 Update company_site/financial/urls.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 16eac8a9e8 Update company_site/financial/tests.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 8b33a179cb Update company_site/financial/templates/financial/index.html for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 1033d28e09 Update company_site/financial/models.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn e70ea3fb96 Update company_site/financial/forms.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 88ee85dda3 Update company_site/financial/admin.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 7ca7721511 Update company_site/company_site/settings/base.py for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn 358231af2e Update .env.prod.example for Stripe invoices (#23) 2026-07-31 12:01:59 -07:00
westfarn eb84d01c03 Add admin Stripe invoices and recurring customer subscriptions.
Closes #23: one-off hosted invoices, monthly Checkout subscriptions, pay-link email, and webhook status sync for admins.
2026-07-31 12:01:59 -07:00
19 changed files with 303 additions and 264 deletions
-3
View File
@@ -34,9 +34,6 @@ EMAIL_HOST_PASSWORD=
EMAIL_PORT=2525
EMAIL_USE_TLS=true
# DEFAULT_FROM_EMAIL=AI ML Operations, LLC <info@aimloperations.com>
# Absolute origin for email logo / footer links
PUBLIC_SITE_URL=https://aimloperations.com
# DEFAULT_FROM_EMAIL=AI ML Operations, LLC <info@aimloperations.com>
# Stripe (test keys from https://dashboard.stripe.com/test/apikeys)
STRIPE_SECRET_KEY=
-1
View File
@@ -35,7 +35,6 @@ EMAIL_HOST_PASSWORD=replace-with-smtp-password
EMAIL_PORT=2525
EMAIL_USE_TLS=true
# DEFAULT_FROM_EMAIL=AI ML Operations, LLC <info@aimloperations.com>
PUBLIC_SITE_URL=https://aimloperations.com
# Stripe (live keys from https://dashboard.stripe.com/apikeys)
# Secret key starts with sk_live_; publishable with pk_live_
@@ -204,8 +204,6 @@ DEFAULT_FROM_EMAIL = env(
"DEFAULT_FROM_EMAIL",
"AI ML Operations, LLC <info@aimloperations.com>",
)
# Absolute site origin for email logo / footer links (no trailing slash).
PUBLIC_SITE_URL = env("PUBLIC_SITE_URL", "https://aimloperations.com").rstrip("/")
# Stripe (invoices / subscriptions — customers pay us)
STRIPE_SECRET_KEY = env("STRIPE_SECRET_KEY", "")
+8 -10
View File
@@ -284,16 +284,14 @@ def send_pay_link_email(
"DEFAULT_FROM_EMAIL",
"AI ML Operations, LLC <info@aimloperations.com>",
)
from public.email_branding import email_brand_context
context = email_brand_context(
customer_name=customer_name,
description=description,
amount_dollars=f"{amount_dollars:.2f}",
pay_url=pay_url,
kind=kind,
subject=subject,
)
context = {
"customer_name": customer_name,
"description": description,
"amount_dollars": f"{amount_dollars:.2f}",
"pay_url": pay_url,
"kind": kind,
"subject": subject,
}
html_content = get_template("emails/invoice_pay_link.html").render(context)
text_content = get_template("emails/invoice_pay_link.txt").render(context)
msg = EmailMultiAlternatives(subject, text_content, from_email, [to_email])
@@ -1,26 +1,48 @@
{% extends "emails/base_email.html" %}
{% block title %}{{ subject }}{% endblock %}
{% block content %}
<p style="margin:0 0 16px;color:#e0e0e0;">Hello {{ customer_name }},</p>
{% if kind == "subscription" %}
<p style="margin:0 0 16px;color:#e0e0e0;">Please complete checkout to start your recurring payment:</p>
{% else %}
<p style="margin:0 0 16px;color:#e0e0e0;">You have a new invoice ready for payment:</p>
{% endif %}
<p style="margin:0 0 8px;color:#e0e0e0;"><strong>{{ description }}</strong></p>
<p class="amount" style="font-size:22px;font-weight:700;color:#00f3ff;margin:12px 0;">${{ amount_dollars }} USD</p>
<p style="margin:24px 0;">
<a class="email-btn" href="{{ pay_url }}" style="display:inline-block;padding:14px 28px;background-color:#00f3ff;color:#0a0a0a !important;text-decoration:none;border-radius:30px;font-weight:700;font-size:14px;letter-spacing:0.5px;text-transform:uppercase;">
{% if kind == "subscription" %}Complete checkout{% else %}Pay invoice{% endif %}
</a>
</p>
<p class="muted" style="color:#a0a0a0;font-size:13px;line-height:1.5;margin:0 0 16px;">
Or open this link:<br>
<a href="{{ pay_url }}" style="color:#00f3ff;word-break:break-all;">{{ pay_url }}</a>
</p>
<p style="margin:0;color:#e0e0e0;">Thank you,<br>{{ brand_legal|default:"AI ML Operations, LLC" }}</p>
{% endblock %}
{% block footer_note %}This is an automated message. Please do not reply to this email.{% endblock %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ subject }}</title>
<style>
body { margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4; }
.email-container { max-width: 600px; margin: 0 auto; background-color: #ffffff; border: 1px solid #dddddd; }
.header { background-color: #0b3d5c; color: #ffffff; padding: 20px; text-align: center; }
.content { padding: 24px; color: #333333; font-size: 15px; line-height: 1.5; }
.btn {
display: inline-block; margin: 20px 0; padding: 12px 24px;
background-color: #0b3d5c; color: #ffffff !important; text-decoration: none;
border-radius: 4px; font-weight: bold;
}
.footer { background-color: #f4f4f4; color: #777777; text-align: center; padding: 12px; font-size: 12px; }
.amount { font-size: 22px; font-weight: bold; margin: 12px 0; }
</style>
</head>
<body>
<div class="email-container">
<div class="header">
<h1>AI ML Operations</h1>
</div>
<div class="content">
<p>Hello {{ customer_name }},</p>
{% if kind == "subscription" %}
<p>Please complete checkout to start your recurring payment:</p>
{% else %}
<p>You have a new invoice ready for payment:</p>
{% endif %}
<p><strong>{{ description }}</strong></p>
<p class="amount">${{ amount_dollars }} USD</p>
<p>
<a class="btn" href="{{ pay_url }}">
{% if kind == "subscription" %}Complete checkout{% else %}Pay invoice{% endif %}
</a>
</p>
<p style="font-size: 13px; color: #666;">Or open this link:<br>{{ pay_url }}</p>
<p>Thank you,<br>AI ML Operations, LLC</p>
</div>
<div class="footer">
<p>This is an automated message. Please do not reply to this email.</p>
</div>
</div>
</body>
</html>
@@ -9,8 +9,4 @@ Amount: ${{ amount_dollars }} USD
{{ pay_url }}
Thank you,
{{ brand_legal|default:"AI ML Operations, LLC" }}
{{ site_url|default:"https://aimloperations.com" }}
Forward-deployed AI engineering
AI ML Operations, LLC
+4 -13
View File
@@ -1,4 +1,3 @@
from django.conf import settings
from django.contrib import admin
from django.core.mail import EmailMultiAlternatives
from django.shortcuts import get_object_or_404
@@ -6,7 +5,6 @@ from django.template.loader import get_template
from django.template.response import TemplateResponse
from django.urls import path
from .email_branding import email_brand_context
from .models import Contact, EmailMessage, PageVisit
@@ -38,12 +36,8 @@ def send_emails(modeladmin, request, queryset):
for email in queryset:
success_count: int = 0
try:
from_email = getattr(
settings,
"DEFAULT_FROM_EMAIL",
"AI ML Operations, LLC <info@aimloperations.com>",
)
d = email_brand_context(title=email.subject, content=email.body)
from_email = "AI ML Operations, LLC <info@aimloperations.com>"
d = {"title": email.subject, "content": email.body}
html_content = get_template("emails/marketing_email.html").render(d)
text_content = get_template("emails/marketing_email.txt").render(d)
@@ -83,11 +77,8 @@ class EmailMessageAdmin(admin.ModelAdmin):
def preview_email(self, request, pk):
email_instance = get_object_or_404(EmailMessage, pk=pk)
context = email_brand_context(
title=email_instance.subject,
content=email_instance.body,
)
return TemplateResponse(request, "emails/marketing_email.html", context)
context = {"title": email_instance.subject, "content": email_instance.body}
return TemplateResponse(request, "public/preview_email.html", context)
@admin.register(PageVisit)
-22
View File
@@ -1,22 +0,0 @@
"""Shared context for branded HTML/text emails."""
from django.conf import settings
from django.contrib.staticfiles.storage import staticfiles_storage
def email_brand_context(**extra):
site_url = getattr(settings, "PUBLIC_SITE_URL", "https://aimloperations.com").rstrip(
"/"
)
logo_path = staticfiles_storage.url("public/img/logo.png")
if logo_path.startswith("http://") or logo_path.startswith("https://"):
logo_url = logo_path
else:
logo_url = f"{site_url}{logo_path}"
return {
"site_url": site_url,
"logo_url": logo_url,
"brand_name": "AI ML Operations",
"brand_legal": "AI ML Operations, LLC",
**extra,
}
@@ -1,107 +0,0 @@
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="dark">
<meta name="supported-color-schemes" content="dark">
<title>{% block title %}{{ brand_name|default:"AI ML Operations" }}{% endblock %}</title>
<!--[if mso]>
<style type="text/css">
body, table, td { font-family: Arial, Helvetica, sans-serif !important; }
</style>
<![endif]-->
<style type="text/css">
body, table, td, a {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table, td {
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
body {
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
background-color: #0a0a0a;
color: #e0e0e0;
font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
a { color: #00f3ff; }
.email-btn {
display: inline-block;
padding: 14px 28px;
background-color: #00f3ff;
color: #0a0a0a !important;
text-decoration: none;
border-radius: 30px;
font-weight: 700;
font-size: 14px;
letter-spacing: 0.5px;
text-transform: uppercase;
}
.muted { color: #a0a0a0; font-size: 13px; line-height: 1.5; }
.amount { font-size: 22px; font-weight: 700; color: #00f3ff; margin: 12px 0; }
.field-label { color: #a0a0a0; font-size: 12px; text-transform: uppercase; letter-spacing: 0.6px; margin: 0 0 4px; }
.field-value { color: #e0e0e0; font-size: 15px; margin: 0 0 16px; line-height: 1.5; }
</style>
</head>
<body style="margin:0;padding:0;background-color:#0a0a0a;">
{% block preheader %}{% endblock %}
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="background-color:#0a0a0a;">
<tr>
<td align="center" style="padding:32px 16px;">
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" style="max-width:600px;background-color:#1a1a1a;border:1px solid rgba(255,255,255,0.1);">
<tr>
<td align="center" style="padding:28px 24px 20px;border-bottom:1px solid rgba(0,243,255,0.35);">
{% if logo_url %}
<a href="{{ site_url|default:'https://aimloperations.com' }}" style="text-decoration:none;">
<img src="{{ logo_url }}" alt="{{ brand_name|default:'AI ML Operations' }}" width="220" style="display:block;width:220px;max-width:80%;height:auto;">
</a>
{% else %}
<p style="margin:0;font-size:18px;font-weight:700;letter-spacing:1px;color:#e0e0e0;text-transform:uppercase;">
{{ brand_name|default:"AI ML Operations" }}
</p>
{% endif %}
{% block header_extra %}{% endblock %}
</td>
</tr>
<tr>
<td style="height:3px;line-height:3px;font-size:0;background-color:#bc13fe;">&nbsp;</td>
</tr>
<tr>
<td style="padding:28px 28px 8px;color:#e0e0e0;font-size:15px;line-height:1.6;font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
{% block content %}{% endblock %}
</td>
</tr>
<tr>
<td style="padding:8px 28px 28px;color:#a0a0a0;font-size:12px;line-height:1.5;text-align:center;border-top:1px solid rgba(255,255,255,0.08);font-family:Inter,-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
{% block footer %}
<p style="margin:16px 0 8px;color:#a0a0a0;">
{% block footer_note %}{% endblock %}
</p>
<p style="margin:0 0 4px;color:#a0a0a0;">
&copy; {% now "Y" %} {{ brand_legal|default:"AI ML Operations, LLC" }}. All rights reserved.
</p>
<p style="margin:0;color:#a0a0a0;">
<a href="{{ site_url|default:'https://aimloperations.com' }}" style="color:#00f3ff;text-decoration:none;">aimloperations.com</a>
&nbsp;·&nbsp; Forward-deployed AI engineering
</p>
{% endblock %}
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
@@ -1,21 +1,110 @@
{% extends "emails/base_email.html" %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New Feedback Submission</title>
<style>
/* Basic reset for email clients */
body, table, td, a {
-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
}
table, td {
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
img {
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
-ms-interpolation-mode: bicubic;
}
body {
margin: 0;
padding: 0;
font-family: Arial, sans-serif;
background-color: #f4f4f4;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
border: 1px solid #dddddd;
}
.header {
background-color: #007BFF;
color: #ffffff;
padding: 20px;
text-align: center;
}
.content {
padding: 20px;
color: #333333;
}
.footer {
background-color: #f4f4f4;
color: #777777;
text-align: center;
padding: 10px;
font-size: 12px;
}
.feedback-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.feedback-text {
font-size: 14px;
line-height: 1.5;
}
</style>
</head>
<body>
<table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0" align="center">
<tr>
<td>
<!-- Email Container -->
<div class="email-container">
<!-- Header -->
<div class="header">
<h1>New Contact Request</h1>
</div>
{% block title %}New Contact Request{% endblock %}
<!-- Content -->
<div class="content">
<p>Hello,</p>
<p>A new feedback item has been submitted. Here are the details:</p>
{% block content %}
<p style="margin:0 0 16px;color:#e0e0e0;">Hello,</p>
<p style="margin:0 0 24px;color:#e0e0e0;">A new contact request was submitted on the site.</p>
<!-- Feedback Title -->
<div class="feedback-title">
Subject: <strong>{{ subject }}</strong>
</div>
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">Subject</p>
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;"><strong>{{ subject }}</strong></p>
<!-- Email -->
<div class="feedback-title">
Email: <strong>{{ email }}</strong>
</div>
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">From</p>
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;">
<a href="mailto:{{ email }}" style="color:#00f3ff;text-decoration:none;">{{ email }}</a>
</p>
<!-- Feedback Text -->
<div class="feedback-text">
<strong>Message:</strong><br>
{{ message }}
</div>
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">Message</p>
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;white-space:pre-wrap;">{{ message }}</p>
{% endblock %}
<p>Thank you for your attention.</p>
</div>
{% block footer_note %}This is an automated message. Please do not reply to this email.{% endblock %}
<!-- Footer -->
<div class="footer">
<p>This is an automated message. Please do not reply to this email.</p>
<p>&copy; 2025 AI ML Operations, LLC. All rights reserved.</p>
</div>
</div>
</td>
</tr>
</table>
</body>
</html>
@@ -1,12 +1,3 @@
New Contact Request — {{ brand_legal|default:"AI ML Operations, LLC" }}
New Contact Request for AI ML Operations, LLC
Subject: {{ subject }}
From: {{ email }}
Message:
{{ message }}
{{ brand_legal|default:"AI ML Operations, LLC" }}
{{ site_url|default:"https://aimloperations.com" }}
Forward-deployed AI engineering
"New Contact. {{ subject }} from {{ email }}. {{ message }}"
@@ -1,15 +1,61 @@
{% extends "emails/base_email.html" %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email Template</title>
<!-- Materialize CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" rel="stylesheet">
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.header {
background-color: #37474f;
color: #ffffff;
padding: 20px;
text-align: center;
}
.content {
padding: 20px;
color: #333333;
}
.footer {
background-color: #333;
padding: 10px;
text-align: center;
font-size: 12px;
color: white;
}
</style>
</head>
<body>
<div class="email-container">
<!-- Header -->
<div class="header">
<h4>{{ title | safe }}</h4>
</div>
{% block title %}{{ title }}{% endblock %}
<!-- Content -->
<div class="content">
{{ content | safe }}
</div>
{% block header_extra %}
{% if title %}
<p style="margin:16px 0 0;font-size:18px;font-weight:600;color:#e0e0e0;line-height:1.4;">{{ title|safe }}</p>
{% endif %}
{% endblock %}
{% block content %}
{{ content|safe }}
{% endblock %}
{% block footer_note %}{% endblock %}
<!-- Footer -->
<div class="footer">
<p>© 2025 AI ML Operations, LLC. All rights reserved.</p>
</div>
</div>
</body>
</html>
@@ -1,8 +1,3 @@
{{ title }}
{{ subject }}
{{ content }}
{{ brand_legal|default:"AI ML Operations, LLC" }}
{{ site_url|default:"https://aimloperations.com" }}
Forward-deployed AI engineering
@@ -1 +1,61 @@
{% extends "emails/marketing_email.html" %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Email Template</title>
<!-- Materialize CSS -->
<link href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css" rel="stylesheet">
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
.email-container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
.header {
background-color: #37474f;
color: #ffffff;
padding: 20px;
text-align: center;
}
.content {
padding: 20px;
color: #333333;
}
.footer {
background-color: #333;
padding: 10px;
text-align: center;
font-size: 12px;
color: white;
}
</style>
</head>
<body>
<div class="email-container">
<!-- Header -->
<div class="header">
<h4>{{ title | safe }}</h4>
</div>
<!-- Content -->
<div class="content">
{{ content | safe }}
</div>
<!-- Footer -->
<div class="footer">
<p>© 2025 AI ML Operations, LLC. All rights reserved.</p>
</div>
</div>
</body>
</html>
+13 -16
View File
@@ -14,25 +14,20 @@ from django.urls import reverse
from django.utils import timezone
from django.views.decorators.http import require_POST
from .email_branding import email_brand_context
from .forms import FormWithCaptcha
from .middleware import get_session_utm
from .models import Contact, EmailMessage, PageVisit
from .traffic import TRAFFIC_TYPE_LABELS, TrafficType
def send_contact_email(email, subject, message):
mail_subject = "New Contact Request for AI ML Operations, LLC"
from_email = getattr(
settings,
"DEFAULT_FROM_EMAIL",
"AI ML Operations, LLC <info@aimloperations.com>",
)
to = "ryan@aimloperations.com"
d = email_brand_context(subject=subject, message=message, email=email)
html_content = get_template("emails/contact_email.html").render(d)
text_content = get_template("emails/contact_email.txt").render(d)
subject = "New Contact Request for AI ML Operations, LLC"
from_email = "ryan@aimloperations.com"
to="ryan@aimloperations.com"
d = {"subject": subject, "message": message, "email": email}
html_content = get_template(r'emails/contact_email.html').render(d)
text_content = get_template(r'emails/contact_email.txt').render(d)
msg = EmailMultiAlternatives(mail_subject, text_content, from_email, [to])
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
msg.attach_alternative(html_content, "text/html")
msg.send(fail_silently=True)
@@ -86,11 +81,13 @@ def terms_of_service(request):
@login_required
def preview_email(request, pk):
email_instance = get_object_or_404(EmailMessage, pk=pk)
context = email_brand_context(
title=email_instance.subject,
content=email_instance.body,
context = {
"title":email_instance.subject,
"content":email_instance.body
}
return render(
request, 'public/preview_email.html', context
)
return render(request, "emails/marketing_email.html", context)
def contact(request):
errors = ''
-11
View File
@@ -1,11 +0,0 @@
# Email previews
Static renders of branded HTML emails (dark neon site UX: `#0a0a0a` / `#1a1a1a` / `#00f3ff` / `#bc13fe`).
| Template | Screenshot |
|----------|------------|
| Contact notify | [contact.png](contact.png) |
| Marketing | [marketing.png](marketing.png) |
| Invoice / pay link | [invoice.png](invoice.png) |
Shared base: `public/templates/emails/base_email.html`.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB