{% extends "base.html" %} {% from "_hub.html" import hub %} {% block title %}Email parsers — karyab{% endblock %} {% block content %}

Email parsers

{% if flash %} {% if flash_error %}
{{ flash }}
{% else %}
{{ flash }}
{% endif %} {% endif %} {% call hub(hub_sections) %}

Active parsers

Built-in parsers (LinkedIn, Indeed) always run first. Custom declarative parsers are matched by sender substring; first match wins.

{% if parsers %}
{% for p in parsers %} {% endfor %}
Name Kind Sender contains Enabled
{{ p.name }} {{ p.kind }} {{ (p.match or {}).get('sender_contains', []) | join(', ') }} {% if p.enabled %}✓{% else %}—{% endif %} {% if p.kind != 'builtin' %} {% endif %}
{% else %}

No parsers configured.

{% endif %}

Recent parse misses

Emails that matched a parser but yielded no jobs. Click "Propose parser" to generate a declarative spec from the email body.

{% if misses %} {% for miss in misses | reverse %} {% endfor %}
Timestamp Subject Sender Parser LLM recovered
{{ miss.get('ts', '')[:19] }} {{ miss.get('subject', '') | truncate(60) }} {{ miss.get('sender', '') | truncate(40) }} {{ miss.get('matched_parser', '') }} {% if miss.get('llm_recovered') %}✓{% else %}—{% endif %}
{% if miss.get('body_html') or miss.get('body_text') %}
{% endif %}
{% else %}

No parse misses recorded yet.

{% endif %}
{% endcall %} {% endblock %}