[GSoC 2026] Proposal: Extend Mail Service with Template API

Hi everyone, and mentors: @Bitmap

I’m planning to apply for GSoC 2026 with MetaBrainz and wanted to share my draft idea for feedback.

Contact Information

Name: Alige Shruthi
GitHub: https://github.com/Shruthii7
Email: shruthialige2004@gmail.com
Timezone: UTC+05:30 (India)

My Contributions

I have started contributing to MetaBrainz, specifically to the ‘mb-mail-service’, which is directly related to this project.

Log warning when unknown email template is requested

PR: https://github.com/metabrainz/mb-mail-service/pull/396

While exploring the template-handling logic, I noticed that when an unknown template ID is requested, the system silently returns ‘None’, which makes debugging difficult.

I added a warning log using ‘tracing: :warn!’ :

_ => {
    tracing::warn!("Unknown email template requested: {}", template_id);
    None
}

This contribution helped me understand the internal flow of template resolution and motivated me to explore ways to improve this system.

Proposed Project

Extend the Mail Service with Template API

Project Overview

While working with the ‘mb-mail-service’, I noticed that all email templates are currently defined inside the service itself. This means that whenever a template is added or modified, the mail service needs to be updated and redeployed.

As more MetaBrainz projects (such as MusicBrainz and ListenBrainz) adopt this service, maintaining and scaling this approach can become difficult.

This project focuses on making the system more flexible by allowing templates to be loaded dynamically via an API rather than being hard-coded in the service.

Problem Statement

  • Templates are tightly coupled with the mail service

  • Adding or updating templates requires redeployment

  • Difficult to manage templates across multiple projects

  • Limited flexibility for future expansion

Proposed Solution

The idea is to extend the mail service so that:

  1. It first checks for templates locally (existing behaviour)

  2. If not found, it fetches the template from an external API

  3. The fetched template is cached for future use

  4. The template is rendered using the existing MJML system

Architecture Overview

User Request
     ↓
Mail Service (Rust)
     ↓
Check Local Templates
     ↓
Not found?
     ↓
Fetch from Template API
     ↓
Cache Template
     ↓
Render (MJML)
     ↓
Send Email

Implementation Plan

1. Extend Template Resolution Logic

Current behavior:

pub fn get(template_id: &str) -> Option<Template> {
    match template_id {
        "basic" => Some(basic::basic),
        _ => None,
    }
}

Proposed change:

pub async fn get(template_id: &str) -> Option<Template> {
    match template_id {
        "basic" => Some(basic::basic),

        _ => {
            tracing::warn!("Unknown template: {}", template_id);

            if let Ok(template) = fetch_template_from_api(template_id).await {
                return Some(template);
            }

            None
        }
    }
}

2. Fetch Templates from API

async fn fetch_template_from_api(template_id: &str) -> Result<Template, Error> {
    let url = format!("https://api.metabrainz.org/templates/{}", template_id);

    let response = reqwest::get(&url).await?;
    let data: TemplateResponse = response.json().await?;

    parse_template(data)
}

3. Example API Response

{
  "template_id": "verify-email",
  "mjml": "<mjml>...</mjml>",
  "translations": {
    "en": {
      "subject": "Verify your email"
    }
  }
}

4. Template Parsing

fn parse_template(data: TemplateResponse) -> Result<Template, Error> {
    let mjml = Mjml::parse(&data.mjml)?;
    Ok(Box::new(move |_, _| Ok(mjml.clone())))
}

5. Add Safe Caching Mechanism

use std::collections::HashMap;
use tokio::sync::RwLock;
use lazy_static::lazy_static;

lazy_static! {
    static ref TEMPLATE_CACHE: RwLock<HashMap<String, Template>> =
        RwLock::new(HashMap::new());
}

This avoids repeated API calls and ensures thread-safe access.

6. Logging and Error Handling

  • Log when templates are fetched from API

  • Handle invalid MJML safely

  • Gracefully fallback if API fails

Timeline

Community Bonding Period

  • Study ‘mb-mail-service’ in detail

  • Discuss API structure and design with mentors

Week 1 & 2

  • Deep dive into the template resolution system

  • Identify integration points for API loading

Week 3

  • Design API client structure

  • Define request/response handling

Week 4

  • Implement the API fetch function

  • Test with mock responses

Week 5

  • Integrate API fallback into ‘get ()’ logic

Week 6

  • Add a caching layer using ‘RwLock’

  • Ensure thread-safe access

Week 7

  • Add MJML validation for fetched templates

Week 8

  • Improve logging and error handling

Week 9

  • Test with real template scenarios

  • Handle edge cases

Week 10

  • Optimize performance and caching

Week 11

  • Write documentation

  • Clean and refactor code

Week 12

  • Final testing and polishing

  • Prepare final submission

Stretch Goals

  • Template versioning support

  • Hot-reloading templates

  • CLI tool for previewing templates

  • Migrating existing templates to an API-based system

Community Affinities

I enjoy listening to a mix of music including pop, indie. Some of the artists I frequently listen to include:

  • Imagine Dragons
    MBID: 012151a8-0f9a-44c9-997f-ebd68b5389f9

  • Billie Eilish
    MBID: f4abc0b5-3f7a-4eff-9e24-6c8d5b7cb7f5

I am still exploring MusicBrainz and learning how MBIDs are used to uniquely identify artists and recordings. I find this concept interesting, especially for building reliable systems around music data.

Programming Precedents

I started programming during my college studies and have since explored various areas, including open-source development.

My main contribution so far has been to the MetaBrainz mb-mail-service repository, where I improved logging for template handling.

I am actively learning by reading real-world codebases and contributing small improvements, and I plan to continue contributing during the GSoC period.

Practical Requirements

I have a personal laptop capable of running Rust development environments and related tools.

My college will be on summer vacation during the GSoC period, so I will be able to dedicate full-time effort (around 40+ hours per week) to this project without academic conflicts.

Conclusion

This project aims to improve the flexibility and scalability of the mail service by decoupling templates from the service itself. By introducing a Template API, templates can be managed independently, updated without redeployment, and reused across multiple MetaBrainz projects.

This will make the system more maintainable and better suited for future growth.

Hi @Shruthii7

I’m not sure that “Fetch Templates from API” is the right approach. (There’s no information about how this external API would be implemented in your proposal either.) I gave that feedback in:

but it doesn’t appear to have been followed in your proposal.

Billie Eilish
MBID: f4abc0b5-3f7a-4eff-9e24-6c8d5b7cb7f5

It doesn’t resolve as a valid MBID for me. Billie Eilish does have the MBID f4abc0b5-3f7a-4eff-8f78-ac078dbce533, which shares the first 16 digits. It makes me think your proposal was generated by an LLM, so I stopped reading there.

3 Likes