# Microservicio de Correo con gRPC

![.NET](https://img.shields.io/badge/.NET-10-blueviolet) ![Docker](https://img.shields.io/badge/Docker-Linux-blue) ![gRPC](https://img.shields.io/badge/Protocolo-gRPC-orange) ![Security](https://img.shields.io/badge/Security-mTLS-green)

Este proyecto es un microservicio backend desarrollado en C# y .NET 10, diseñado para centralizar las operaciones de correo electrónico (envío y lectura) con un servidor Microsoft Exchange. Proporciona una API gRPC para ser consumida por otros microservicios internos.

## Características Principales

* **API gRPC:** Comunicación eficiente definida por contrato estricto (`.proto`).
* **Envío de Correos (`SendMail`):** Soporta múltiples destinatarios (TO, CC), asunto, cuerpo (HTML o texto) y archivos adjuntos.
* **Lectura de Bandeja de Entrada (`ReadInbox`):** Permite filtrar correos por remitente, asunto, estado (no leídos) y rango de fechas.
* **Conexión a Exchange (EWS):**
    * Implementación robusta utilizando **`IHttpClientFactory`** para la gestión eficiente de conexiones HTTP **(Mejora .NET 10: Gestión Optimizada de Sockets)**.
    * Construcción manual de peticiones SOAP/XML para garantizar compatibilidad total con Exchange 2013 y manejo correcto de adjuntos en entornos Linux.
* **Seguridad Dual:**
    * **Salida (Exchange):** Validación SSL personalizada ("scoped") configurada mediante `HttpClientHandler`, reemplazando la configuración global obsoleta `ServicePointManager` **(Mejora .NET 10: Seguridad Granular sin Legacy)**.
    * **Entrada (Clientes):** Soporte para **mTLS (Mutual TLS)** exigiendo certificados de cliente cargados vía `CreateFromPemFile` **(Mejora .NET 10: Carga Nativa PEM)**.
* **Contenerizado:** Optimizado para ejecución en contenedores Docker (Linux) utilizando las imágenes base `mcr.microsoft.com/dotnet/aspnet:10.0`.

## Stack Tecnológico

* **Framework:** .NET 10 (ASP.NET Core) **(Mejoras de Rendimiento JIT/GC)**
* **Lenguaje:** C#
* **Protocolo:** gRPC (HTTP/2)
* **Cliente HTTP:** Patrón `IHttpClientFactory` + `HttpClient` inyectado **(Gestión Optimizada de Sockets)**
* **Contenerización:** Docker (Linux)

## Configuración

El servicio se configura a través de un sistema jerárquico estándar de .NET.

### Archivo `appsettings.json`

Este archivo contiene la configuración base.

**Ejemplo:**
```json
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
    }
  },
  "MailSettings": {
    "EmailAddress": "cuenta-de-servicio@triara.com",
    "Password": "", 
    "EwsUrl": "https://outlook.triara.com/ews/exchange.asmx"
  }
}
```

### Manejo de Secretos
**¡Importante!** Las credenciales y otros datos sensibles nunca deben guardarse en el `appsettings.json` del repositorio.

- **Desarrollo**: Usa "User Secrets" de .NET.
- **Producción**: Inyecta secretos como variables de entorno o volúmenes de Kubernetes.


## Seguridad y Certificados
El servicio utiliza una arquitectura de certificados para mTLS.

- **Puerto 8080 (Interno):** Tráfico gRPC sobre HTTP/2 sin encriptación (h2c). Ideal para comunicación dentro de la red privada de Docker o detrás de un Proxy.
- **Puerto 8081 (Seguro):** Tráfico gRPC sobre HTTPS con mTLS. Requiere que el cliente presente un certificado válido firmado por la CA interna (`ca.crt`).


**Ruta de Certificados en el Contenedor:** `/app/certs/` Se espera encontrar: `server.crt`, `server.key` y `ca.crt`.

## Ejecución
### 1. **Ejecución Local (Visual Studio)**

1. El proyecto cuenta con un `Program.cs` híbrido que detecta el entorno de desarrollo.
2. Abre el proyecto en Visual Studio.
3. Selecciona el perfil "**http**".
4. Presiona **F5**.
5. El servicio usará el puerto definido en `launchSettings.json` (ej. **5194**).
6. **Postman**: Conectar a `localhost:5194` (Sin TLS).



### 2. **Ejecución con Docker**

Para producción o pruebas de integración completas.

  1. **Construye la imagen:**
  
    `docker build -t email-microservice .`

  2. **Ejecuta el contenedor:** Es necesario mapear los puertos y montar los volúmenes de configuración y certificados.

    docker run -d \
    -p 5001:8080 \
    -p 5002:8081 \
    -v "C:\Ruta\A\Tu\appsettings.json:/app/appsettings.json" \
    -v "C:\Ruta\A\Tus\Certificados:/app/certs" \
    --name email-service email-microservice
  
  **Puerto 5001:** Acceso HTTP (Inseguro).
  
  **Puerto 5002:** Acceso HTTPS (Seguro / mTLS).

## Pruebas (Postman)

Las pruebas de integración se gestionan a través de un Workspace compartido.

- **URL del Workspace:** https://dao111.postman.co/workspace/Microservicio-Correo~cca1fab1-5653-4d12-b146-3e8b08ee9fc3/collection/68af860fbc88542b2e04c05e?action=share&creator=34379515

### Configuración para mTLS en Postman (Puerto 5002)

1. Ir a **Settings > Certificates**.
2. **Client Certificate:**
    -   Host: `localhost`
    -   Port: `5002`
    -   Cargar `client.crt` y `client.key`.


3. **CA Certificates:**
- Activar y cargar `ca.crt`.

## Referencia de la API (`email.proto`)

Protocol Buffers

```
syntax = "proto3";

import "google/protobuf/timestamp.proto";
package exchangeMail;
option csharp_namespace = "EmailMicroservice.Protos";

message EmailAttachment {
    string filename = 1;
    bytes content = 2; // contenido en binario
    string mime_type = 3; 
    string content_id = 4; 
    bool is_inline = 5;    
}

message EmailMessage {
    string from = 1;
    repeated string to = 2;
    repeated string cc = 3;
    string subject = 4;
    string body = 5;
    repeated EmailAttachment attachments = 6;
    string id = 7;
}

message SendMailRequest {
    EmailMessage email = 1;
}

message SendMailResponse {
    bool success = 1;
    string message = 2;
}

message ReadInboxRequest {
    int32 max_results = 1;
    google.protobuf.Timestamp start_date = 2;
    google.protobuf.Timestamp end_date = 3;
    string filter_from = 4;
    string filter_subject = 5;
    bool unread_only = 6;
    bool include_attachments = 7;
}

message ReadInboxResponse {
    repeated EmailMessage emails = 1;
    int32 total_count = 2;
}

message GetItemDetailsRequest {
  string item_id = 1;
}

message GetItemDetailsResponse {
  EmailMessage email = 1;
}

service ExchangeMailService {
    rpc SendMail(SendMailRequest) returns (SendMailResponse);
    rpc ReadInbox(ReadInboxRequest) returns (ReadInboxResponse);
    rpc GetItemDetails(GetItemDetailsRequest) returns (GetItemDetailsResponse);
}
```
