# π§ PEC (POSTA ELETTRONICA CERTIFICATA) - MCP INTEGRATION
**Data aggiornamento**: 2025-11-24
**Status**: β οΈ **OUTPUT SIZE ISSUE - SOLUZIONE IDENTIFICATA**
---
## π INDICE
1. [Overview](#overview)
2. [Architettura](#architettura)
3. [Tool MCP Implementati](#tool-mcp-implementati)
4. [Use Cases & Workflow](#use-cases--workflow)
5. [Sbustamento PEC (Unwrapping)](#sbustamento-pec-unwrapping)
6. [Provider PEC Supportati](#provider-pec-supportati)
7. [Implementazione Tecnica](#implementazione-tecnica)
8. [Testing](#testing)
---
## π― OVERVIEW
### Obiettivo
Integrare la gestione di **PEC (Posta Elettronica Certificata)** come tool MCP in IRIS, permettendo all'agente LLM di:
- Leggere email PEC da IMAP con **sbustamento automatico** (estrazione da postacert.eml)
- Estrarre allegati del messaggio originale
- Inviare PEC via SMTP
- Gestire metadati di certificazione (daticert.xml)
### Architettura High-Level
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β IRIS Agent (LLM) β
β β
β "Controlla la mia PEC e dimmi quali allegati ho ricevuto" β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β MCP Protocol
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β IRIS MCP Server (http_server.py) β
β β
β Tool disponibili per l'agente: β
β β’ pec_list_messages β lista PEC con sbustamento β
β β’ pec_get_message β legge singola PEC con unwrapping β
β β’ pec_get_attachment β estrae allegato da PEC β
β β’ pec_send_message β invia PEC via SMTP β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PECOperations (Internal) β
β β
β β’ IMAP Client (imaplib) β
β β’ SMTP Client (smtplib) β
β β’ PECUnwrapper (sbustamento postacert.eml) β
β β’ Provider Auto-detection (Legalmail, Aruba, PosteCert) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
### Differenza con Infocert
| Aspetto | Infocert MCP | PEC MCP |
|---------|--------------|---------|
| **Architettura** | Server SSE esterno | Operazioni interne (come Microsoft Graph) |
| **Protocollo** | SSE + JSON-RPC | Diretto (IMAP/SMTP Python) |
| **Servizio** | Terze parti (UAT server) | Interno IRIS |
| **Credenziali** | Username/password/PIN conversazionale | Email/password conversazionale |
---
## ποΈ ARCHITETTURA
### Pattern: Internal Operations
PEC segue il pattern di **Microsoft Graph Operations**, non quello di Infocert SSE:
```
User Request
β
IRIS Agent
β
http_server.py (tool dispatcher)
β
PECOperations.execute(action, params)
β
IMAP/SMTP + PECUnwrapper
β
Result (unwrapped PEC data)
```
### Flusso Lettura PEC
```
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 1. Agent riceve richiesta: "Controlla la mia PEC" β
ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 2. Agent chiede: "Fornisci email e password PEC" β
ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 3. User fornisce: β
β - pec_email: filippo.savarese@legalmail.it β
β - pec_password: ******** β
ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 4. Tool: pec_list_messages β
β β Auto-detect provider (Legalmail) β
β β Connect IMAP (mbox.cert.legalmail.it:993) β
β β List messages β
β β Check is_pec_message() per ogni email β
ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 5. Per ogni PEC trovata: β
β β unwrap_pec() automatico β
β β Estrae postacert.eml (messaggio originale) β
β β Estrae daticert.xml (metadati certificazione) β
β β Lista allegati del messaggio originale β
ββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 6. Ritorna risultato con original_message unwrapped β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
---
## π§ TOOL MCP IMPLEMENTATI
### 1. `pec_list_messages`
**Descrizione**: Elenca messaggi PEC da INBOX con sbustamento automatico.
**Input:**
```json
{
"pec_email": "filippo.savarese@legalmail.it",
"pec_password": "mypassword",
"folder": "INBOX",
"max_results": 10
}
```
**Output:**
```json
{
"messages": [
{
"id": "123",
"subject": "CONSEGNA: Lettera denuncia sinistro",
"from": "posta-certificata@telecompost.it",
"to": "filippo.savarese@legalmail.it",
"date": "Wed, 4 Jun 2025 11:37:33 +0200",
"is_pec": true,
"pec_type": "delivery",
"has_attachments": true
}
],
"total": 6
}
```
**Note:**
- Auto-detection provider dal dominio email (@legalmail.it β Legalmail)
- `is_pec` = true se contiene postacert.eml e daticert.xml
- `pec_type`: "normal", "delivery", "acceptance", "error"
---
### 2. `pec_get_message`
**Descrizione**: Ottiene messaggio singolo con **sbustamento automatico completo**.
**Input:**
```json
{
"pec_email": "filippo.savarese@legalmail.it",
"pec_password": "mypassword",
"message_id": "123"
}
```
**Output:**
```json
{
"is_pec": true,
"pec_type": "delivery",
"container": {
"from": "posta-certificata@telecompost.it",
"to": "filippo.savarese@legalmail.it",
"subject": "CONSEGNA: Lettera denuncia sinistro",
"date": "Wed, 4 Jun 2025 11:37:33 +0200",
"message_id": "<abc123@postacert>"
},
"original_message": {
"from": "sender@example.com",
"to": "filippo.savarese@legalmail.it",
"subject": "Lettera denuncia sinistro vettura",
"date": "Wed, 4 Jun 2025 10:00:00 +0200",
"message_id": "<original123@sender>",
"body_text": "Contenuto del messaggio originale...",
"body_html": "<html>...",
"attachments": [
{
"filename": "denuncia_sinistro.pdf",
"content_type": "application/pdf",
"size": 245632,
"data": "base64..."
}
]
},
"daticert": "<?xml version=\"1.0\"?>\n<postacert>...",
"metadata": {
"certification_type": "delivery",
"date": "2025-06-04T11:37:33+02:00",
"sender": "sender@example.com",
"recipient": "filippo.savarese@legalmail.it"
}
}
```
**Flusso Unwrapping:**
1. Scarica messaggio completo via IMAP
2. Parse container email
3. Cerca allegato `postacert.eml`
4. Estrae e parsa messaggio originale da postacert.eml
5. Estrae allegati del messaggio originale (esclusi file sistema PEC)
6. Cerca e parsa `daticert.xml` per metadati certificazione
7. Ritorna struttura completa unwrapped
**File Sistema PEC esclusi dagli allegati:**
- `postacert.eml` (messaggio originale unwrapped)
- `daticert.xml` (metadati certificazione)
- `smime.p7s` / `smime.p7m` (firma digitale)
---
### 3. `pec_get_attachment`
**Descrizione**: Estrae allegato specifico da messaggio PEC unwrapped.
**Input:**
```json
{
"pec_email": "filippo.savarese@legalmail.it",
"pec_password": "mypassword",
"message_id": "123",
"attachment_index": 0
}
```
**Output:**
```json
{
"filename": "denuncia_sinistro.pdf",
"content_type": "application/pdf",
"size": 245632,
"data": "JVBERi0xLjQKJeLjz9MKMyAwIG9..."
}
```
**Note:**
- `attachment_index` Γ¨ 0-based
- Ritorna attachment del **messaggio originale unwrapped**, non del container
- `data` Γ¨ base64 encoded
---
### 4. `pec_send_message`
**Descrizione**: Invia PEC via SMTP.
**Input:**
```json
{
"pec_email": "filippo.savarese@legalmail.it",
"pec_password": "mypassword",
"to": "recipient@example.com",
"subject": "Notifica importante",
"body": "Testo del messaggio...",
"attachments": [
{
"filename": "documento.pdf",
"data": "base64..."
}
]
}
```
**Output:**
```json
{
"success": true,
"message": "Email sent successfully"
}
```
---
## π― USE CASES & WORKFLOW
### Use Case 1: Lettura PEC con estrazione allegati
**Richiesta utente:**
> "Controlla la mia PEC e dimmi quali allegati ho ricevuto oggi"
**Agent workflow:**
```
1. Agent chiede credenziali PEC:
"Per accedere alla tua PEC, fornisci:"
- Email PEC
- Password
2. User fornisce:
filippo.savarese@legalmail.it / ********
3. pec_list_messages(pec_email, pec_password, max_results=10)
β trova 6 messaggi, 4 sono PEC
4. Per ogni PEC con has_attachments=true:
pec_get_message(message_id)
β unwrap automatico, estrae original_message
5. Agent risponde:
"π§ Hai ricevuto 4 PEC oggi:
1. Da: sender@example.com
Oggetto: Lettera denuncia sinistro
Allegati:
- denuncia_sinistro.pdf (240 KB)
- foto_danno.jpg (1.2 MB)
2. Da: company@pec.it
Oggetto: Fattura n. 12345
Allegati:
- fattura_12345.pdf (85 KB)"
```
---
### Use Case 2: Scarica PDF da PEC e firma digitalmente
**Richiesta utente:**
> "Scarica il PDF dalla mia ultima PEC, firmalo con Infocert e rimandalo"
**Agent workflow:**
```
1. Chiede credenziali PEC β user fornisce
2. pec_list_messages(max_results=1)
β trova ultima PEC
3. pec_get_message(message_id)
β unwrap, trova attachment PDF index 0
4. pec_get_attachment(message_id, attachment_index=0)
β scarica PDF base64
5. Chiede credenziali Infocert β user fornisce
6. Upload PDF su storage temporaneo β ottiene URL
7. infocert_sign_document(username, password, pin, pdf_url)
β firma PDF, ottiene signed_url
8. Download signed PDF da signed_url
9. pec_send_message(
pec_email, pec_password,
to=original_sender,
subject="Re: " + original_subject,
body="In allegato il documento firmato",
attachments=[{filename: "documento_firmato.pdf", data: base64}]
)
10. Agent risponde:
"β
PDF scaricato dalla PEC, firmato digitalmente con Infocert
e reinviato via PEC al mittente originale"
```
---
### Use Case 3: Workflow automatico PEC β Teams
**Richiesta utente:**
> "Quando arriva una PEC con PDF, caricalo automaticamente su Teams nel canale Contratti"
**Agent workflow:**
```
1. Chiede credenziali PEC
2. pec_list_messages(max_results=20)
β filtra solo PEC con has_attachments=true
3. Per ogni PEC:
a) pec_get_message(message_id)
β unwrap, estrae allegati PDF
b) Per ogni PDF:
pec_get_attachment(message_id, index)
β scarica PDF base64
c) teams_send_message(
chat_id="Contratti",
message="Nuovo documento PEC ricevuto",
attachment=pdf_data
)
4. Agent risponde:
"β
Caricati 5 PDF da PEC su Teams:
- denuncia_sinistro.pdf (da PEC del 04/06)
- fattura_12345.pdf (da PEC del 03/06)
- contratto_firmato.pdf (da PEC del 02/06)"
```
---
## π¦ SBUSTAMENTO PEC (UNWRAPPING)
### Struttura Email PEC
Una PEC contiene 3 componenti principali:
```
Email Container (envelope PEC)
β
βββ postacert.eml β MESSAGGIO ORIGINALE
β βββ headers (From, To, Subject, Date originali)
β βββ body (testo/HTML originale)
β βββ attachments (allegati originali)
β
βββ daticert.xml β METADATI CERTIFICAZIONE
β βββ tipo certificazione (consegna/accettazione/errore)
β βββ data/ora certificazione
β βββ mittente/destinatario
β βββ info provider PEC
β
βββ smime.p7s β FIRMA DIGITALE
βββ certificato provider PEC
```
### Algoritmo Unwrapping
```python
def unwrap_pec(raw_email: bytes) -> Dict:
# 1. Parse container
container_msg = parser.parsebytes(raw_email)
# 2. Verifica se Γ¨ PEC
is_pec = is_pec_message(container_msg)
# Controlla: X-Trasporto: posta-certificata
# Cerca: postacert.eml e daticert.xml
# 3. Estrai postacert.eml
for part in container_msg.walk():
if part.get_filename() == 'postacert.eml':
original_msg = parser.parsebytes(part.get_payload(decode=True))
# 4. Estrai allegati da original_msg
attachments = []
for part in original_msg.walk():
if part.get_content_disposition() == 'attachment':
if filename not in PEC_SYSTEM_FILES: # escludi postacert.eml, daticert.xml, smime.p7s
attachments.append({
'filename': filename,
'data': base64.b64encode(payload)
})
# 5. Estrai daticert.xml
daticert_xml = extract_daticert(container_msg)
metadata = parse_daticert_metadata(daticert_xml)
return {
'is_pec': True,
'container': {...},
'original_message': {
'from': original_msg['From'],
'subject': original_msg['Subject'],
'body_text': get_text_content(original_msg),
'attachments': attachments
},
'daticert': daticert_xml,
'metadata': metadata
}
```
### Tipi di PEC
| Tipo | Subject Pattern | Significato |
|------|-----------------|-------------|
| **delivery** | `CONSEGNA:`, `avvenuta consegna` | Ricevuta di consegna (messaggio consegnato) |
| **acceptance** | `ACCETTAZIONE:`, `presa in carico` | Ricevuta di accettazione (messaggio accettato dal provider) |
| **error** | `ANOMALIA:`, `mancata consegna`, `errore` | Errore nella consegna |
| **normal** | Altro | PEC normale (messaggio originale) |
---
## π PROVIDER PEC SUPPORTATI
### Auto-detection Provider
Il sistema riconosce automaticamente il provider PEC dal dominio email:
```python
PEC_PROVIDERS = {
'legalmail': {
'domains': ['@legalmail.it'],
'imap_host': 'mbox.cert.legalmail.it',
'imap_port': 993,
'smtp_host': 'sendm.cert.legalmail.it',
'smtp_port': 465
},
'aruba': {
'domains': ['@pec.it', '@arubapec.it'],
'imap_host': 'imaps.pec.aruba.it',
'imap_port': 993,
'smtp_host': 'smtps.pec.aruba.it',
'smtp_port': 465
},
'postecert': {
'domains': ['@postecert.it'],
'imap_host': 'imap.postecert.it',
'imap_port': 993,
'smtp_host': 'smtp.postecert.it',
'smtp_port': 465
}
}
```
### Aggiungere Provider Custom
Per provider non riconosciuti, l'agent puΓ² richiedere parametri IMAP/SMTP:
```python
config = get_provider_config(
email="user@customerpec.it",
imap_host="imap.customerpec.it", # Custom
smtp_host="smtp.customerpec.it" # Custom
)
```
---
## π» IMPLEMENTAZIONE TECNICA
### File Structure
```
iris/
βββ src/
β βββ mcp_servers/
β βββ http_server.py # MCP server principale (modificato)
β βββ pec/
β βββ __init__.py # Export PECOperations
β βββ pec_operations.py # Implementazione tool PEC
β βββ pec_unwrapper.py # Sbustamento PEC
β βββ pec_providers.py # Config provider IMAP/SMTP
βββ test_pec_simple.py # Test IMAP connection
```
---
### PECOperations Class
**File:** `src/mcp_servers/pec/pec_operations.py`
```python
class PECOperations(BaseOperation):
"""Operations for PEC (Italian Certified Email) via IMAP/SMTP."""
def __init__(self, graph_client=None):
self.graph_client = graph_client
self.area_name = "pec"
self.unwrapper = PECUnwrapper()
def get_supported_actions(self) -> List[str]:
return ["list_messages", "get_message", "send_message", "get_attachment"]
def _connect_imap(self, pec_email: str, pec_password: str) -> imaplib.IMAP4_SSL:
# Auto-detect provider
config = get_provider_config(pec_email)
# Connect IMAP SSL
mail = imaplib.IMAP4_SSL(config['imap_host'], config['imap_port'])
mail.login(pec_email, pec_password)
return mail
def _list_messages(self, params: Dict) -> Dict:
mail = self._connect_imap(params['pec_email'], params['pec_password'])
mail.select("INBOX")
# List messages
status, msg_nums = mail.search(None, "ALL")
# For each message, check if PEC
messages = []
for msg_id in msg_nums[-max_results:]:
msg_data = mail.fetch(msg_id, "(BODY.PEEK[HEADER])")
msg = email.message_from_bytes(msg_data[0][1])
is_pec = self.unwrapper.is_pec_message(msg)
messages.append({
'id': msg_id,
'subject': msg['Subject'],
'is_pec': is_pec,
...
})
return {'messages': messages, 'total': len(msg_nums)}
```
---
### PECUnwrapper Class
**File:** `src/mcp_servers/pec/pec_unwrapper.py`
```python
class PECUnwrapper:
def is_pec_message(self, message: EmailMessage) -> bool:
"""Check if message is PEC"""
# Check X-Trasporto: posta-certificata
if 'posta-certificata' in message.get('X-Trasporto', ''):
return True
# Check subject patterns
subject = message.get('Subject', '').lower()
if any(p in subject for p in ['posta certificata:', 'consegna:', 'accettazione:']):
return True
# Check attachments
has_postacert = False
has_daticert = False
for part in message.walk():
filename = part.get_filename()
if filename:
if 'postacert.eml' in filename.lower():
has_postacert = True
if 'daticert.xml' in filename.lower():
has_daticert = True
return has_postacert and has_daticert
def unwrap_pec(self, raw_email: bytes) -> Dict:
"""Full PEC unwrapping"""
container_msg = self.parser.parsebytes(raw_email)
# Extract postacert.eml
original_msg = self.extract_original_message(container_msg)
# Extract attachments
attachments = self.extract_attachments(original_msg, skip_pec_files=True)
# Extract daticert.xml
daticert = self.extract_daticert(container_msg)
metadata = self._parse_daticert_metadata(daticert)
return {
'is_pec': True,
'pec_type': self._detect_pec_type(container_msg),
'container': {...},
'original_message': {
'from': original_msg['From'],
'attachments': attachments
},
'daticert': daticert,
'metadata': metadata
}
```
---
### Integration in http_server.py
**1. Import:**
```python
from .pec import PECOperations
```
**2. Inizializzazione:**
```python
pec_ops = PECOperations()
```
**3. Registrazione tool in MCP_TOOLS:**
```python
MCP_TOOLS = {
# ... altri tool ...
"pec_list_messages": {
"description": "List PEC messages with automatic unwrapping...",
"inputSchema": {
"type": "object",
"properties": {
"pec_email": {"type": "string"},
"pec_password": {"type": "string"},
"folder": {"type": "string", "default": "INBOX"},
"max_results": {"type": "integer", "default": 10}
},
"required": ["pec_email", "pec_password"]
}
},
# ... altri 3 tool PEC ...
}
```
**4. Handler:**
```python
elif tool_name == "pec_list_messages":
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(
None,
pec_ops.execute,
"list_messages",
params
)
return result
```
---
## π§ͺ TESTING
### Test IMAP Connection (Legalmail)
**File:** `test_pec_simple.py`
```bash
cd /workspace/iris
python test_pec_simple.py
```
**Result:**
```
β
Connected to mbox.cert.legalmail.it:993
β
Login successful for filippo.savarese@legalmail.it
β
Found 6 messages
π§ Last message:
From: posta-certificata@telecompost.it
Subject: CONSEGNA: Lettera denuncia sinistro vettura FB94696
Date: Wed, 4 Jun 2025 11:37:33 +0200
β
ALL TESTS PASSED - PEC IMAP is working!
```
### Credenziali Test (Legalmail)
```
Email: filippo.savarese@legalmail.it
Password: 85D@k!K|
Provider: Legalmail
IMAP: mbox.cert.legalmail.it:993 (SSL)
SMTP: sendm.cert.legalmail.it:465 (SSL)
```
### Test End-to-End (Browser TrustySign)
1. Aprire: https://trustypa.brainaihub.tech/trustysign/
2. Messaggio: "Controlla la mia PEC"
3. Agent chiede credenziali PEC
4. Fornire: filippo.savarese@legalmail.it / 85D@k!K|
5. Agent esegue `pec_list_messages`
6. Agent mostra lista PEC con sbustamento automatico
7. Richiedere dettagli: "Mostrami i dettagli della prima PEC"
8. Agent esegue `pec_get_message` con unwrapping completo
9. Se ha allegati: "Scarica il primo allegato"
10. Agent esegue `pec_get_attachment`
---
## π COMPARISON: PEC vs Infocert vs Microsoft
| Feature | PEC MCP | Infocert MCP | Microsoft Graph MCP |
|---------|---------|--------------|---------------------|
| **Architettura** | Internal operations | External SSE server | Internal operations |
| **Protocollo** | IMAP/SMTP nativo | MCP over SSE | REST API Graph |
| **Credenziali** | Email/password conversazionale | Username/password/PIN conversazionale | OAuth 2.0 |
| **Provider** | Auto-detection (Legalmail, Aruba, PosteCert) | Infocert UAT server | Microsoft 365 |
| **Unwrapping** | β
Automatico (postacert.eml) | β N/A | β N/A |
| **File esclusi** | β
Esclude file sistema PEC | β N/A | β N/A |
| **Metadata** | β
daticert.xml parsed | β N/A | β N/A |
| **Testing** | β
IMAP test passed (6 messages) | β οΈ Blocked (external UAT 400) | β
OAuth working |
---
## β
STATUS
### Completato
- β
PECOperations con IMAP/SMTP
- β
PECUnwrapper con sbustamento completo
- β
Provider auto-detection (Legalmail, Aruba, PosteCert)
- β
4 tools integrati in http_server.py
- β
Test IMAP connection successful (Legalmail)
- β
Commit: `d911c38` - feat: Add PEC MCP integration
### β οΈ Problema Identificato (2025-11-24)
- β `pec_get_message` output troppo grande β supera context limit agent LangGraph
- **Causa**: body_text (5KB+) + body_html (50KB+) + daticert.xml (2KB) = 50-100KB total
- **Impatto**: Agent LLM non riesce a processare il risultato
- **Soluzione**: Implementare `compact=True` mode (vedi sezione sotto)
### Da Testare
- β³ Test unwrapping con PEC reale (postacert.eml)
- β³ Test download allegati
- β³ Test invio PEC via SMTP
---
## π NEXT STEPS
### 1. **FIX OUTPUT SIZE (Priority 1)** β οΈ
**Problema**: `pec_get_message` ritorna 50-100KB output β supera limit agent LangGraph
**Soluzione Rapida - Compact Mode**:
Modificare `src/mcp_servers/pec/pec_unwrapper.py`:
```python
def unwrap_pec(self, raw_email: bytes,
include_attachment_data: bool = False,
compact: bool = True) -> Dict[str, Any]: # β DEFAULT compact=True
"""
Args:
compact: Se True, omette body completo e ritorna solo preview (riduce output 98%)
"""
# ... parsing container ...
if compact:
# COMPACT: solo preview 300 chars
body_text = self._get_text_content(original_msg)
result['original_message'] = {
'from': ...,
'subject': ...,
'body_preview': body_text[:300] + '...',
'body_length': len(body_text),
'has_html': len(body_html) > 0,
'attachments': [...] # solo metadata
}
# NO body_text completo
# NO body_html completo
# NO daticert XML completo
else:
# FULL: tutto incluso (per usi specifici)
result['original_message'] = {
'body_text': self._get_text_content(original_msg),
'body_html': self._get_html_content(original_msg),
...
}
```
**Output size**:
- Prima: 100KB (body completo)
- Dopo: 2KB (compact mode) β
- Riduzione: 98%
**Test**:
```bash
python test_pec_compact.py
```
### 2. **Deploy Fix**
```bash
cd /opt/iris && ./deploy.sh
```
### 3. **Test con Agent LangGraph**
Verificare che l'agent riesca a processare il risultato compatto.
### 4. **Estensioni Future**
- Supporto ricerca PEC (per mittente, data, allegati)
- Tool `pec_get_message_body` separato per body completo (se necessario)
- Cache credenziali PEC (come OAuth)
- Integration con Infocert (PEC β firma β reinvia)
---
## π REFERENCES
- **PEC Standard**: https://www.agid.gov.it/it/piattaforme/posta-elettronica-certificata-pec
- **Legalmail IMAP/SMTP**: mbox.cert.legalmail.it:993 / sendm.cert.legalmail.it:465
- **Python imaplib**: https://docs.python.org/3/library/imaplib.html
- **Python email**: https://docs.python.org/3/library/email.html
---
**Data ultima modifica**: 2025-11-10
**Autore**: IRIS Team
**Versione**: 1.0.0