diff --git a/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.hbs b/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.hbs
new file mode 100644
index 00000000000..2efc6e7ae74
--- /dev/null
+++ b/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.hbs
@@ -0,0 +1,104 @@
+
+
+
+
+
+ | |
+
+
+
+
+
+
+
+
+
+
+
+ {{#if siteIconUrl}}
+
+  |
+
+ {{/if}}
+
+
+ Your gift is ready to share!
+ Share the link below with the recipient to let them redeem their gift membership.
+
+
+
+
+
+
+ |
+ Gift subscription
+ {{gift.tierName}} ({{gift.cadenceLabel}})
+ Amount paid
+ {{gift.amount}}
+ |
+
+
+ |
+
+
+
+
+
+
+
+ |
+ Redemption link
+ {{gift.link}}
+ This link can be redeemed once and expires on {{gift.expiresAt}}.
+ |
+
+
+ |
+
+
+
+
+ |
+ This message was sent from {{siteDomain}} to {{toEmail}}
+ |
+
+
+ |
+ You received this email because you purchased a gift subscription on {{siteTitle}}.
+ |
+
+
+
+
+ |
+
+
+
+
+
+
+
+
+ |
+ |
+
+
+
+
diff --git a/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts b/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts
new file mode 100644
index 00000000000..79d891a61e1
--- /dev/null
+++ b/ghost/core/core/server/services/gifts/email-templates/gift-purchase-confirmation.ts
@@ -0,0 +1,30 @@
+export interface GiftPurchaseConfirmationData {
+ siteTitle: string;
+ siteDomain: string;
+ toEmail: string;
+ gift: {
+ amount: string;
+ tierName: string;
+ cadenceLabel: string;
+ link: string;
+ expiresAt: string;
+ };
+}
+
+export function renderText(data: GiftPurchaseConfirmationData): string {
+ return `Your gift is ready to share!
+
+Share the link below with the recipient to let them redeem their gift membership.
+
+Gift subscription: ${data.gift.tierName} (${data.gift.cadenceLabel})
+Amount paid: ${data.gift.amount}
+
+Redemption link: ${data.gift.link}
+
+This link can be redeemed once and expires on ${data.gift.expiresAt}.
+
+---
+
+Sent to ${data.toEmail} from ${data.siteDomain}.
+You received this email because you purchased a gift subscription on ${data.siteTitle}.`;
+}
diff --git a/ghost/core/core/server/services/gifts/gift-email-renderer.ts b/ghost/core/core/server/services/gifts/gift-email-renderer.ts
new file mode 100644
index 00000000000..08d71ea7e87
--- /dev/null
+++ b/ghost/core/core/server/services/gifts/gift-email-renderer.ts
@@ -0,0 +1,28 @@
+import {promises as fs} from 'node:fs';
+import path from 'node:path';
+import Handlebars from 'handlebars';
+import type {GiftPurchaseConfirmationData} from './email-templates/gift-purchase-confirmation';
+import {renderText as renderPurchaseConfirmationText} from './email-templates/gift-purchase-confirmation';
+
+export class GiftEmailRenderer {
+ private readonly handlebars: typeof Handlebars;
+
+ private purchaseConfirmationTemplate: HandlebarsTemplateDelegate | null = null;
+
+ constructor() {
+ this.handlebars = Handlebars.create();
+ }
+
+ async renderPurchaseConfirmation(data: GiftPurchaseConfirmationData): Promise<{html: string; text: string}> {
+ if (!this.purchaseConfirmationTemplate) {
+ const source = await fs.readFile(path.join(__dirname, './email-templates/gift-purchase-confirmation.hbs'), 'utf8');
+
+ this.purchaseConfirmationTemplate = this.handlebars.compile(source);
+ }
+
+ return {
+ html: this.purchaseConfirmationTemplate(data),
+ text: renderPurchaseConfirmationText(data)
+ };
+ }
+}
diff --git a/ghost/core/core/server/services/gifts/gift-email-service.ts b/ghost/core/core/server/services/gifts/gift-email-service.ts
new file mode 100644
index 00000000000..8ec400e6c5b
--- /dev/null
+++ b/ghost/core/core/server/services/gifts/gift-email-service.ts
@@ -0,0 +1,115 @@
+import moment from 'moment';
+import {GiftEmailRenderer} from './gift-email-renderer';
+
+interface Mailer {
+ send(message: {
+ to: string;
+ subject: string;
+ html: string;
+ text: string;
+ from: string;
+ forceTextContent: boolean;
+ }): Promise