Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
03bb01664f | ||
|
|
b98f504afc | ||
|
|
05aa0b96b1 |
@@ -34,6 +34,9 @@ EMAIL_HOST_PASSWORD=
|
|||||||
EMAIL_PORT=2525
|
EMAIL_PORT=2525
|
||||||
EMAIL_USE_TLS=true
|
EMAIL_USE_TLS=true
|
||||||
# DEFAULT_FROM_EMAIL=AI ML Operations, LLC <info@aimloperations.com>
|
# 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 (test keys from https://dashboard.stripe.com/test/apikeys)
|
||||||
STRIPE_SECRET_KEY=
|
STRIPE_SECRET_KEY=
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ EMAIL_HOST_PASSWORD=replace-with-smtp-password
|
|||||||
EMAIL_PORT=2525
|
EMAIL_PORT=2525
|
||||||
EMAIL_USE_TLS=true
|
EMAIL_USE_TLS=true
|
||||||
# DEFAULT_FROM_EMAIL=AI ML Operations, LLC <info@aimloperations.com>
|
# 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)
|
# Stripe (live keys from https://dashboard.stripe.com/apikeys)
|
||||||
# Secret key starts with sk_live_; publishable with pk_live_
|
# Secret key starts with sk_live_; publishable with pk_live_
|
||||||
|
|||||||
@@ -204,6 +204,8 @@ DEFAULT_FROM_EMAIL = env(
|
|||||||
"DEFAULT_FROM_EMAIL",
|
"DEFAULT_FROM_EMAIL",
|
||||||
"AI ML Operations, LLC <info@aimloperations.com>",
|
"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 (invoices / subscriptions — customers pay us)
|
||||||
STRIPE_SECRET_KEY = env("STRIPE_SECRET_KEY", "")
|
STRIPE_SECRET_KEY = env("STRIPE_SECRET_KEY", "")
|
||||||
|
|||||||
@@ -284,14 +284,16 @@ def send_pay_link_email(
|
|||||||
"DEFAULT_FROM_EMAIL",
|
"DEFAULT_FROM_EMAIL",
|
||||||
"AI ML Operations, LLC <info@aimloperations.com>",
|
"AI ML Operations, LLC <info@aimloperations.com>",
|
||||||
)
|
)
|
||||||
context = {
|
from public.email_branding import email_brand_context
|
||||||
"customer_name": customer_name,
|
|
||||||
"description": description,
|
context = email_brand_context(
|
||||||
"amount_dollars": f"{amount_dollars:.2f}",
|
customer_name=customer_name,
|
||||||
"pay_url": pay_url,
|
description=description,
|
||||||
"kind": kind,
|
amount_dollars=f"{amount_dollars:.2f}",
|
||||||
"subject": subject,
|
pay_url=pay_url,
|
||||||
}
|
kind=kind,
|
||||||
|
subject=subject,
|
||||||
|
)
|
||||||
html_content = get_template("emails/invoice_pay_link.html").render(context)
|
html_content = get_template("emails/invoice_pay_link.html").render(context)
|
||||||
text_content = get_template("emails/invoice_pay_link.txt").render(context)
|
text_content = get_template("emails/invoice_pay_link.txt").render(context)
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to_email])
|
msg = EmailMultiAlternatives(subject, text_content, from_email, [to_email])
|
||||||
|
|||||||
@@ -1,48 +1,26 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "emails/base_email.html" %}
|
||||||
<html lang="en">
|
|
||||||
<head>
|
{% block title %}{{ subject }}{% endblock %}
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{% block content %}
|
||||||
<title>{{ subject }}</title>
|
<p style="margin:0 0 16px;color:#e0e0e0;">Hello {{ customer_name }},</p>
|
||||||
<style>
|
{% if kind == "subscription" %}
|
||||||
body { margin: 0; padding: 0; font-family: Arial, sans-serif; background-color: #f4f4f4; }
|
<p style="margin:0 0 16px;color:#e0e0e0;">Please complete checkout to start your recurring payment:</p>
|
||||||
.email-container { max-width: 600px; margin: 0 auto; background-color: #ffffff; border: 1px solid #dddddd; }
|
{% else %}
|
||||||
.header { background-color: #0b3d5c; color: #ffffff; padding: 20px; text-align: center; }
|
<p style="margin:0 0 16px;color:#e0e0e0;">You have a new invoice ready for payment:</p>
|
||||||
.content { padding: 24px; color: #333333; font-size: 15px; line-height: 1.5; }
|
{% endif %}
|
||||||
.btn {
|
<p style="margin:0 0 8px;color:#e0e0e0;"><strong>{{ description }}</strong></p>
|
||||||
display: inline-block; margin: 20px 0; padding: 12px 24px;
|
<p class="amount" style="font-size:22px;font-weight:700;color:#00f3ff;margin:12px 0;">${{ amount_dollars }} USD</p>
|
||||||
background-color: #0b3d5c; color: #ffffff !important; text-decoration: none;
|
<p style="margin:24px 0;">
|
||||||
border-radius: 4px; font-weight: bold;
|
<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 %}
|
||||||
.footer { background-color: #f4f4f4; color: #777777; text-align: center; padding: 12px; font-size: 12px; }
|
</a>
|
||||||
.amount { font-size: 22px; font-weight: bold; margin: 12px 0; }
|
</p>
|
||||||
</style>
|
<p class="muted" style="color:#a0a0a0;font-size:13px;line-height:1.5;margin:0 0 16px;">
|
||||||
</head>
|
Or open this link:<br>
|
||||||
<body>
|
<a href="{{ pay_url }}" style="color:#00f3ff;word-break:break-all;">{{ pay_url }}</a>
|
||||||
<div class="email-container">
|
</p>
|
||||||
<div class="header">
|
<p style="margin:0;color:#e0e0e0;">Thank you,<br>{{ brand_legal|default:"AI ML Operations, LLC" }}</p>
|
||||||
<h1>AI ML Operations</h1>
|
{% endblock %}
|
||||||
</div>
|
|
||||||
<div class="content">
|
{% block footer_note %}This is an automated message. Please do not reply to this email.{% endblock %}
|
||||||
<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,4 +9,8 @@ Amount: ${{ amount_dollars }} USD
|
|||||||
{{ pay_url }}
|
{{ pay_url }}
|
||||||
|
|
||||||
Thank you,
|
Thank you,
|
||||||
AI ML Operations, LLC
|
{{ brand_legal|default:"AI ML Operations, LLC" }}
|
||||||
|
|
||||||
|
—
|
||||||
|
{{ site_url|default:"https://aimloperations.com" }}
|
||||||
|
Forward-deployed AI engineering
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
from django.conf import settings
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from django.core.mail import EmailMultiAlternatives
|
from django.core.mail import EmailMultiAlternatives
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
@@ -5,6 +6,7 @@ from django.template.loader import get_template
|
|||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
|
||||||
|
from .email_branding import email_brand_context
|
||||||
from .models import Contact, EmailMessage, PageVisit
|
from .models import Contact, EmailMessage, PageVisit
|
||||||
|
|
||||||
|
|
||||||
@@ -36,8 +38,12 @@ def send_emails(modeladmin, request, queryset):
|
|||||||
for email in queryset:
|
for email in queryset:
|
||||||
success_count: int = 0
|
success_count: int = 0
|
||||||
try:
|
try:
|
||||||
from_email = "AI ML Operations, LLC <info@aimloperations.com>"
|
from_email = getattr(
|
||||||
d = {"title": email.subject, "content": email.body}
|
settings,
|
||||||
|
"DEFAULT_FROM_EMAIL",
|
||||||
|
"AI ML Operations, LLC <info@aimloperations.com>",
|
||||||
|
)
|
||||||
|
d = email_brand_context(title=email.subject, content=email.body)
|
||||||
|
|
||||||
html_content = get_template("emails/marketing_email.html").render(d)
|
html_content = get_template("emails/marketing_email.html").render(d)
|
||||||
text_content = get_template("emails/marketing_email.txt").render(d)
|
text_content = get_template("emails/marketing_email.txt").render(d)
|
||||||
@@ -77,8 +83,11 @@ class EmailMessageAdmin(admin.ModelAdmin):
|
|||||||
|
|
||||||
def preview_email(self, request, pk):
|
def preview_email(self, request, pk):
|
||||||
email_instance = get_object_or_404(EmailMessage, pk=pk)
|
email_instance = get_object_or_404(EmailMessage, pk=pk)
|
||||||
context = {"title": email_instance.subject, "content": email_instance.body}
|
context = email_brand_context(
|
||||||
return TemplateResponse(request, "public/preview_email.html", context)
|
title=email_instance.subject,
|
||||||
|
content=email_instance.body,
|
||||||
|
)
|
||||||
|
return TemplateResponse(request, "emails/marketing_email.html", context)
|
||||||
|
|
||||||
|
|
||||||
@admin.register(PageVisit)
|
@admin.register(PageVisit)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
"""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,
|
||||||
|
}
|
||||||
@@ -63,13 +63,6 @@ PUBLIC_PAGE_ENTRIES = (
|
|||||||
"0.7",
|
"0.7",
|
||||||
"Custom workstation and server builds optimized for AI and ML workloads.",
|
"Custom workstation and server builds optimized for AI and ML workloads.",
|
||||||
),
|
),
|
||||||
(
|
|
||||||
"file_hosting",
|
|
||||||
"File Hosting",
|
|
||||||
"monthly",
|
|
||||||
"0.7",
|
|
||||||
"Managed file hosting and storage for teams that need reliable data access.",
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"web_design",
|
"web_design",
|
||||||
"Web Design and Hosting",
|
"Web Design and Hosting",
|
||||||
@@ -104,7 +97,6 @@ SERVICE_URL_NAMES = frozenset({
|
|||||||
"ai_sensor",
|
"ai_sensor",
|
||||||
"ai_education",
|
"ai_education",
|
||||||
"computers",
|
"computers",
|
||||||
"file_hosting",
|
|
||||||
"web_design",
|
"web_design",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 843 KiB |
|
Before Width: | Height: | Size: 3.4 MiB |
|
Before Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 142 KiB |
@@ -69,7 +69,7 @@
|
|||||||
<li><a href="{% url 'public_index' %}"
|
<li><a href="{% url 'public_index' %}"
|
||||||
class="{% if request.resolver_match.url_name == 'public_index' %}active{% endif %}">Home</a></li>
|
class="{% if request.resolver_match.url_name == 'public_index' %}active{% endif %}">Home</a></li>
|
||||||
<li class="dropdown">
|
<li class="dropdown">
|
||||||
<button type="button" class="nav-dropdown-trigger{% if request.resolver_match.url_name in 'forward_deployed,ai_education,ai_sensor,bot,chat,computers,file_hosting,ml_model,web_design' %} active{% endif %}"
|
<button type="button" class="nav-dropdown-trigger{% if request.resolver_match.url_name in 'forward_deployed,ai_education,ai_sensor,bot,chat,computers,ml_model,web_design' %} active{% endif %}"
|
||||||
id="services-menu-button" aria-expanded="false" aria-haspopup="true" aria-controls="services-menu">Services</button>
|
id="services-menu-button" aria-expanded="false" aria-haspopup="true" aria-controls="services-menu">Services</button>
|
||||||
<ul class="dropdown-content" id="services-menu" role="menu" aria-labelledby="services-menu-button">
|
<ul class="dropdown-content" id="services-menu" role="menu" aria-labelledby="services-menu-button">
|
||||||
<li><a href="{% url 'forward_deployed' %}">Forward-Deployed AI</a></li>
|
<li><a href="{% url 'forward_deployed' %}">Forward-Deployed AI</a></li>
|
||||||
@@ -79,7 +79,6 @@
|
|||||||
<li><a href="{% url 'ai_sensor' %}">Sensors</a></li>
|
<li><a href="{% url 'ai_sensor' %}">Sensors</a></li>
|
||||||
<li><a href="{% url 'ai_education' %}">Education</a></li>
|
<li><a href="{% url 'ai_education' %}">Education</a></li>
|
||||||
<li><a href="{% url 'computers' %}">Hardware</a></li>
|
<li><a href="{% url 'computers' %}">Hardware</a></li>
|
||||||
<li><a href="{% url 'file_hosting' %}">Hosting</a></li>
|
|
||||||
<li><a href="{% url 'web_design' %}">Web Design</a></li>
|
<li><a href="{% url 'web_design' %}">Web Design</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -0,0 +1,107 @@
|
|||||||
|
<!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;"> </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;">
|
||||||
|
© {% 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>
|
||||||
|
· Forward-deployed AI engineering
|
||||||
|
</p>
|
||||||
|
{% endblock %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,110 +1,21 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "emails/base_email.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>
|
|
||||||
|
|
||||||
<!-- Content -->
|
{% block title %}New Contact Request{% endblock %}
|
||||||
<div class="content">
|
|
||||||
<p>Hello,</p>
|
|
||||||
<p>A new feedback item has been submitted. Here are the details:</p>
|
|
||||||
|
|
||||||
<!-- Feedback Title -->
|
{% block content %}
|
||||||
<div class="feedback-title">
|
<p style="margin:0 0 16px;color:#e0e0e0;">Hello,</p>
|
||||||
Subject: <strong>{{ subject }}</strong>
|
<p style="margin:0 0 24px;color:#e0e0e0;">A new contact request was submitted on the site.</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Email -->
|
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">Subject</p>
|
||||||
<div class="feedback-title">
|
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;"><strong>{{ subject }}</strong></p>
|
||||||
Email: <strong>{{ email }}</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Feedback Text -->
|
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">From</p>
|
||||||
<div class="feedback-text">
|
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;">
|
||||||
<strong>Message:</strong><br>
|
<a href="mailto:{{ email }}" style="color:#00f3ff;text-decoration:none;">{{ email }}</a>
|
||||||
{{ message }}
|
</p>
|
||||||
</div>
|
|
||||||
|
|
||||||
<p>Thank you for your attention.</p>
|
<p class="field-label" style="color:#a0a0a0;font-size:12px;text-transform:uppercase;letter-spacing:0.6px;margin:0 0 4px;">Message</p>
|
||||||
</div>
|
<p class="field-value" style="color:#e0e0e0;font-size:15px;margin:0 0 16px;white-space:pre-wrap;">{{ message }}</p>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
<!-- Footer -->
|
{% block footer_note %}This is an automated message. Please do not reply to this email.{% endblock %}
|
||||||
<div class="footer">
|
|
||||||
<p>This is an automated message. Please do not reply to this email.</p>
|
|
||||||
<p>© 2025 AI ML Operations, LLC. All rights reserved.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
New Contact Request for AI ML Operations, LLC
|
New Contact Request — {{ brand_legal|default:"AI ML Operations, LLC" }}
|
||||||
|
|
||||||
"New Contact. {{ subject }} from {{ email }}. {{ message }}"
|
Subject: {{ subject }}
|
||||||
|
From: {{ email }}
|
||||||
|
|
||||||
|
Message:
|
||||||
|
{{ message }}
|
||||||
|
|
||||||
|
—
|
||||||
|
{{ brand_legal|default:"AI ML Operations, LLC" }}
|
||||||
|
{{ site_url|default:"https://aimloperations.com" }}
|
||||||
|
Forward-deployed AI engineering
|
||||||
|
|||||||
@@ -1,61 +1,15 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "emails/base_email.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 -->
|
{% block title %}{{ title }}{% endblock %}
|
||||||
<div class="content">
|
|
||||||
{{ content | safe }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Footer -->
|
{% block header_extra %}
|
||||||
<div class="footer">
|
{% if title %}
|
||||||
<p>© 2025 AI ML Operations, LLC. All rights reserved.</p>
|
<p style="margin:16px 0 0;font-size:18px;font-weight:600;color:#e0e0e0;line-height:1.4;">{{ title|safe }}</p>
|
||||||
</div>
|
{% endif %}
|
||||||
</div>
|
{% endblock %}
|
||||||
</body>
|
|
||||||
</html>
|
{% block content %}
|
||||||
|
{{ content|safe }}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block footer_note %}{% endblock %}
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
{{ subject }}
|
{{ title }}
|
||||||
|
|
||||||
{{ content }}
|
{{ content }}
|
||||||
|
|
||||||
|
—
|
||||||
|
{{ brand_legal|default:"AI ML Operations, LLC" }}
|
||||||
|
{{ site_url|default:"https://aimloperations.com" }}
|
||||||
|
Forward-deployed AI engineering
|
||||||
|
|||||||
@@ -1,90 +0,0 @@
|
|||||||
{% extends "base.html" %}
|
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}File Hosting - AI ML Operations, LLC{% endblock %}
|
|
||||||
{% block meta_description %}Secure, scalable, and reliable file hosting with weekly backups by AI ML Operations, LLC.
|
|
||||||
Protect your data with our advanced storage solutions.{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
<!-- Hero Section -->
|
|
||||||
<div class="hero-section" style="height: 40vh; min-height: 300px;">
|
|
||||||
<div class="hero-content">
|
|
||||||
<h1 class="hero-title">File Hosting</h1>
|
|
||||||
<p class="hero-subtitle">Secure, Scalable, and Reliable File Storage with Weekly Backups</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- About File Hosting Section -->
|
|
||||||
<div class="section">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="section-title">About Our File Hosting Service</h2>
|
|
||||||
<p style="text-align: center; max-width: 800px; margin: 0 auto; color: var(--text-muted); font-size: 1.1rem;">
|
|
||||||
At AI ML Operations, we provide secure and scalable file hosting solutions tailored to your business needs. Our
|
|
||||||
platform ensures your data is always accessible, protected, and backed up with weekly backups for added peace of
|
|
||||||
mind. Whether you're storing critical business documents, media files, or large datasets, our file hosting service
|
|
||||||
is designed to meet your requirements with reliability and efficiency.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Features Section -->
|
|
||||||
<div class="section" style="background: var(--surface-color);">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="section-title">What We Offer</h2>
|
|
||||||
<div class="card-grid">
|
|
||||||
<div class="card" style="text-align: center;">
|
|
||||||
<h5 class="card-title">Secure Storage</h5>
|
|
||||||
<p class="card-text">Your files are stored securely with advanced encryption protocols.</p>
|
|
||||||
</div>
|
|
||||||
<div class="card" style="text-align: center;">
|
|
||||||
<h5 class="card-title">Weekly Backups</h5>
|
|
||||||
<p class="card-text">Automatic weekly backups to ensure your data is always safe.</p>
|
|
||||||
</div>
|
|
||||||
<div class="card" style="text-align: center;">
|
|
||||||
<h5 class="card-title">Scalable Solutions</h5>
|
|
||||||
<p class="card-text">Easily scale your storage as your business grows.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Benefits Section -->
|
|
||||||
<div class="section">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="section-title">Why Choose Us?</h2>
|
|
||||||
<div class="card-grid">
|
|
||||||
<div class="card">
|
|
||||||
<img src="{% static 'public/img/file_hosting/card-1.jpg' %}" alt="Data Security"
|
|
||||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
|
||||||
<span class="card-title">Data Security</span>
|
|
||||||
<p class="card-text">Advanced encryption and access controls to protect your files.</p>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<img src="{% static 'public/img/file_hosting/card-2.jpg' %}" alt="Reliability"
|
|
||||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
|
||||||
<span class="card-title">Reliability</span>
|
|
||||||
<p class="card-text">99.9% uptime guarantee for uninterrupted access to your files.</p>
|
|
||||||
</div>
|
|
||||||
<div class="card">
|
|
||||||
<img src="{% static 'public/img/file_hosting/card-3.jpg' %}" alt="Easy Management"
|
|
||||||
style="width: 100%; border-radius: 8px; margin-bottom: 1rem;">
|
|
||||||
<span class="card-title">Easy Management</span>
|
|
||||||
<p class="card-text">User-friendly interface for seamless file management.</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Call to Action Section -->
|
|
||||||
<div class="section" style="text-align: center;">
|
|
||||||
<div class="container">
|
|
||||||
<h2 class="section-title">Ready to Secure Your Files?</h2>
|
|
||||||
<p class="hero-subtitle" style="margin-bottom: 2rem;">Contact us today to get started with our file hosting service.
|
|
||||||
</p>
|
|
||||||
<a href="{% url 'contact' %}" class="btn"
|
|
||||||
data-tianji-event="service_cta" data-tianji-event-page="file_hosting" data-tianji-event-action="get_started">Get Started</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
@@ -53,10 +53,6 @@
|
|||||||
<h3>Web Design</h3>
|
<h3>Web Design</h3>
|
||||||
<p>Elevate your online presence with captivating web design that blends creativity with functionality. Our expert designers craft visually stunning websites that engage your audience and drive conversions, ensuring a seamless user experience across all devices.</p>
|
<p>Elevate your online presence with captivating web design that blends creativity with functionality. Our expert designers craft visually stunning websites that engage your audience and drive conversions, ensuring a seamless user experience across all devices.</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
|
||||||
<h3>File Hosting</h3>
|
|
||||||
<p>Securely store and share your files with ease using our reliable file hosting platform. With robust encryption and flexible access controls, you can confidently manage your data, collaborate seamlessly, and streamline your workflow.</p>
|
|
||||||
</div>
|
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<h3>App Virtualization</h3>
|
<h3>App Virtualization</h3>
|
||||||
<p>Transform your software delivery with our app virtualization solutions, enabling seamless access to applications from any device, anywhere. Experience enhanced flexibility, scalability, and security as we optimize your IT infrastructure for the digital age.</p>
|
<p>Transform your software delivery with our app virtualization solutions, enabling seamless access to applications from any device, anywhere. Experience enhanced flexibility, scalability, and security as we optimize your IT infrastructure for the digital age.</p>
|
||||||
|
|||||||
@@ -219,12 +219,6 @@
|
|||||||
<p class="card-text">Servers and workstations for compute, storage, and local inference workloads.</p>
|
<p class="card-text">Servers and workstations for compute, storage, and local inference workloads.</p>
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<a href="{% url 'file_hosting' %}" class="card"
|
|
||||||
data-tianji-event="service_click" data-tianji-event-service="File Hosting">
|
|
||||||
<span class="card-title">File Hosting</span>
|
|
||||||
<p class="card-text">Secure, scalable file hosting to store and share your data.</p>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,61 +1 @@
|
|||||||
<!DOCTYPE html>
|
{% extends "emails/marketing_email.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>
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from django.views.generic import RedirectView
|
||||||
|
|
||||||
from . import seo, views
|
from . import seo, views
|
||||||
|
|
||||||
@@ -12,7 +13,11 @@ urlpatterns = [
|
|||||||
path("computer", views.computers, name="computers"),
|
path("computer", views.computers, name="computers"),
|
||||||
path("web_design", views.web_design, name="web_design"),
|
path("web_design", views.web_design, name="web_design"),
|
||||||
path("ai_sensor", views.ai_sensor, name="ai_sensor"),
|
path("ai_sensor", views.ai_sensor, name="ai_sensor"),
|
||||||
path("file_hosting", views.file_hosting, name="file_hosting"),
|
# Permanent redirect: product retired; keep URL for inbound links/search results.
|
||||||
|
path(
|
||||||
|
"file_hosting",
|
||||||
|
RedirectView.as_view(pattern_name="public_index", permanent=True),
|
||||||
|
),
|
||||||
path("bot_creation", views.bot, name="bot"),
|
path("bot_creation", views.bot, name="bot"),
|
||||||
path("forward-deployed-ai", views.forward_deployed, name="forward_deployed"),
|
path("forward-deployed-ai", views.forward_deployed, name="forward_deployed"),
|
||||||
path("ml_model", views.ml_model, name="ml_model"),
|
path("ml_model", views.ml_model, name="ml_model"),
|
||||||
|
|||||||
@@ -14,20 +14,25 @@ from django.urls import reverse
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.views.decorators.http import require_POST
|
from django.views.decorators.http import require_POST
|
||||||
|
|
||||||
|
from .email_branding import email_brand_context
|
||||||
from .forms import FormWithCaptcha
|
from .forms import FormWithCaptcha
|
||||||
from .middleware import get_session_utm
|
from .middleware import get_session_utm
|
||||||
from .models import Contact, EmailMessage, PageVisit
|
from .models import Contact, EmailMessage, PageVisit
|
||||||
from .traffic import TRAFFIC_TYPE_LABELS, TrafficType
|
from .traffic import TRAFFIC_TYPE_LABELS, TrafficType
|
||||||
|
|
||||||
def send_contact_email(email, subject, message):
|
def send_contact_email(email, subject, message):
|
||||||
subject = "New Contact Request for AI ML Operations, LLC"
|
mail_subject = "New Contact Request for AI ML Operations, LLC"
|
||||||
from_email = "ryan@aimloperations.com"
|
from_email = getattr(
|
||||||
to="ryan@aimloperations.com"
|
settings,
|
||||||
d = {"subject": subject, "message": message, "email": email}
|
"DEFAULT_FROM_EMAIL",
|
||||||
html_content = get_template(r'emails/contact_email.html').render(d)
|
"AI ML Operations, LLC <info@aimloperations.com>",
|
||||||
text_content = get_template(r'emails/contact_email.txt').render(d)
|
)
|
||||||
|
to = "ryan@aimloperations.com"
|
||||||
msg = EmailMultiAlternatives(subject, text_content, from_email, [to])
|
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)
|
||||||
|
|
||||||
|
msg = EmailMultiAlternatives(mail_subject, text_content, from_email, [to])
|
||||||
msg.attach_alternative(html_content, "text/html")
|
msg.attach_alternative(html_content, "text/html")
|
||||||
msg.send(fail_silently=True)
|
msg.send(fail_silently=True)
|
||||||
|
|
||||||
@@ -66,9 +71,6 @@ def web_design(request):
|
|||||||
def ai_sensor(request):
|
def ai_sensor(request):
|
||||||
return render(request, "public/ai_sensor.html", {})
|
return render(request, "public/ai_sensor.html", {})
|
||||||
|
|
||||||
def file_hosting(request):
|
|
||||||
return render(request, "public/file_hosting.html", {})
|
|
||||||
|
|
||||||
def bot(request):
|
def bot(request):
|
||||||
return render(request, "public/bot.html", {})
|
return render(request, "public/bot.html", {})
|
||||||
|
|
||||||
@@ -84,13 +86,11 @@ def terms_of_service(request):
|
|||||||
@login_required
|
@login_required
|
||||||
def preview_email(request, pk):
|
def preview_email(request, pk):
|
||||||
email_instance = get_object_or_404(EmailMessage, pk=pk)
|
email_instance = get_object_or_404(EmailMessage, pk=pk)
|
||||||
context = {
|
context = email_brand_context(
|
||||||
"title":email_instance.subject,
|
title=email_instance.subject,
|
||||||
"content":email_instance.body
|
content=email_instance.body,
|
||||||
}
|
|
||||||
return render(
|
|
||||||
request, 'public/preview_email.html', context
|
|
||||||
)
|
)
|
||||||
|
return render(request, "emails/marketing_email.html", context)
|
||||||
|
|
||||||
def contact(request):
|
def contact(request):
|
||||||
errors = ''
|
errors = ''
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# 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`.
|
||||||
|
After Width: | Height: | Size: 46 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 38 KiB |